UNPKG

aws-cdk

Version:

CDK Toolkit, the command line tool for CDK apps

633 lines 77.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const client_cloudformation_1 = require("@aws-sdk/client-cloudformation"); const client_lambda_1 = require("@aws-sdk/client-lambda"); const client_sfn_1 = require("@aws-sdk/client-sfn"); const evaluate_cloudformation_template_1 = require("../../../lib/api/evaluate-cloudformation-template"); const common_1 = require("../../../lib/api/hotswap/common"); const mock_sdk_1 = require("../../util/mock-sdk"); const silent_1 = require("../../util/silent"); const setup = require("../hotswap/hotswap-test-setup"); jest.mock('@aws-sdk/client-lambda', () => { const original = jest.requireActual('@aws-sdk/client-lambda'); return { ...original, waitUntilFunctionUpdated: jest.fn(), }; }); let hotswapMockSdkProvider; let sdk; beforeEach(() => { sdk = new mock_sdk_1.MockSdk(); sdk.getUrlSuffix = () => Promise.resolve('amazonaws.com'); jest.resetAllMocks(); hotswapMockSdkProvider = setup.setupHotswapTests(); }); describe.each([common_1.HotswapMode.FALL_BACK, common_1.HotswapMode.HOTSWAP_ONLY])('%p mode', (hotswapMode) => { (0, silent_1.silentTest)('returns a deployStackResult with noOp=true when it receives an empty set of changes', async () => { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, setup.cdkStackArtifactOf()); // THEN expect(deployStackResult).not.toBeUndefined(); expect(deployStackResult?.noOp).toBeTruthy(); expect(deployStackResult?.stackArn).toEqual(setup.STACK_ID); }); (0, silent_1.silentTest)('A change to only a non-hotswappable resource results in a full deployment for HOTSWAP and a noOp for HOTSWAP_ONLY', async () => { // GIVEN setup.setCurrentCfnStackTemplate({ Resources: { SomethingElse: { Type: 'AWS::CloudFormation::SomethingElse', Properties: { Prop: 'old-value', }, }, }, }); const cdkStackArtifact = setup.cdkStackArtifactOf({ template: { Resources: { SomethingElse: { Type: 'AWS::CloudFormation::SomethingElse', Properties: { Prop: 'new-value', }, }, }, }, }); if (hotswapMode === common_1.HotswapMode.FALL_BACK) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).toBeUndefined(); expect(mock_sdk_1.mockStepFunctionsClient).not.toHaveReceivedCommand(client_sfn_1.UpdateStateMachineCommand); expect(mock_sdk_1.mockLambdaClient).not.toHaveReceivedCommand(client_lambda_1.UpdateFunctionCodeCommand); } else if (hotswapMode === common_1.HotswapMode.HOTSWAP_ONLY) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).not.toBeUndefined(); expect(deployStackResult?.noOp).toEqual(true); expect(mock_sdk_1.mockStepFunctionsClient).not.toHaveReceivedCommand(client_sfn_1.UpdateStateMachineCommand); expect(mock_sdk_1.mockLambdaClient).not.toHaveReceivedCommand(client_lambda_1.UpdateFunctionCodeCommand); } }); (0, silent_1.silentTest)('A change to both a hotswappable resource and a non-hotswappable resource results in a full deployment for HOTSWAP and a noOp for HOTSWAP_ONLY', async () => { // GIVEN setup.setCurrentCfnStackTemplate({ Resources: { Func: { Type: 'AWS::Lambda::Function', Properties: { Code: { S3Bucket: 'current-bucket', S3Key: 'current-key', }, FunctionName: 'my-function', }, Metadata: { 'aws:asset:path': 'old-path', }, }, SomethingElse: { Type: 'AWS::CloudFormation::SomethingElse', Properties: { Prop: 'old-value', }, }, }, }); const cdkStackArtifact = setup.cdkStackArtifactOf({ template: { Resources: { Func: { Type: 'AWS::Lambda::Function', Properties: { Code: { S3Bucket: 'current-bucket', S3Key: 'new-key', }, FunctionName: 'my-function', }, Metadata: { 'aws:asset:path': 'new-path', }, }, SomethingElse: { Type: 'AWS::CloudFormation::SomethingElse', Properties: { Prop: 'new-value', }, }, }, }, }); if (hotswapMode === common_1.HotswapMode.FALL_BACK) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).toBeUndefined(); expect(mock_sdk_1.mockStepFunctionsClient).not.toHaveReceivedCommand(client_sfn_1.UpdateStateMachineCommand); expect(mock_sdk_1.mockLambdaClient).not.toHaveReceivedCommand(client_lambda_1.UpdateFunctionCodeCommand); } else if (hotswapMode === common_1.HotswapMode.HOTSWAP_ONLY) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).not.toBeUndefined(); expect(mock_sdk_1.mockLambdaClient).toHaveReceivedCommandWith(client_lambda_1.UpdateFunctionCodeCommand, { FunctionName: 'my-function', S3Bucket: 'current-bucket', S3Key: 'new-key', }); expect(mock_sdk_1.mockStepFunctionsClient).not.toHaveReceivedCommand(client_sfn_1.UpdateStateMachineCommand); } }); (0, silent_1.silentTest)('changes only to CDK::Metadata result in a noOp', async () => { // GIVEN setup.setCurrentCfnStackTemplate({ Resources: { MetaData: { Type: 'AWS::CDK::Metadata', Properties: { Prop: 'old-value', }, }, }, }); const cdkStackArtifact = setup.cdkStackArtifactOf({ template: { Resources: { MetaData: { Type: 'AWS::CDK::Metadata', Properties: { Prop: 'new-value', }, }, }, }, }); // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).not.toBeUndefined(); expect(deployStackResult?.noOp).toEqual(true); expect(mock_sdk_1.mockStepFunctionsClient).not.toHaveReceivedCommand(client_sfn_1.UpdateStateMachineCommand); expect(mock_sdk_1.mockLambdaClient).not.toHaveReceivedCommand(client_lambda_1.UpdateFunctionCodeCommand); }); (0, silent_1.silentTest)('resource deletions require full deployments for HOTSWAP and a noOp for HOTSWAP_ONLY', async () => { // GIVEN setup.setCurrentCfnStackTemplate({ Resources: { Machine: { Type: 'AWS::StepFunctions::StateMachine', }, }, }); const cdkStackArtifact = setup.cdkStackArtifactOf(); if (hotswapMode === common_1.HotswapMode.FALL_BACK) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).toBeUndefined(); expect(mock_sdk_1.mockStepFunctionsClient).not.toHaveReceivedCommand(client_sfn_1.UpdateStateMachineCommand); expect(mock_sdk_1.mockLambdaClient).not.toHaveReceivedCommand(client_lambda_1.UpdateFunctionCodeCommand); } else if (hotswapMode === common_1.HotswapMode.HOTSWAP_ONLY) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).not.toBeUndefined(); expect(deployStackResult?.noOp).toEqual(true); expect(mock_sdk_1.mockStepFunctionsClient).not.toHaveReceivedCommand(client_sfn_1.UpdateStateMachineCommand); expect(mock_sdk_1.mockLambdaClient).not.toHaveReceivedCommand(client_lambda_1.UpdateFunctionCodeCommand); } }); (0, silent_1.silentTest)('can correctly reference AWS::Partition in hotswappable changes', async () => { // GIVEN setup.setCurrentCfnStackTemplate({ Resources: { Func: { Type: 'AWS::Lambda::Function', Properties: { Code: { S3Bucket: 'current-bucket', S3Key: 'current-key', }, FunctionName: { 'Fn::Join': ['', [{ Ref: 'AWS::Partition' }, '-', 'my-function']], }, }, Metadata: { 'aws:asset:path': 'new-path', }, }, }, }); const cdkStackArtifact = setup.cdkStackArtifactOf({ template: { Resources: { Func: { Type: 'AWS::Lambda::Function', Properties: { Code: { S3Bucket: 'current-bucket', S3Key: 'new-key', }, FunctionName: { 'Fn::Join': ['', [{ Ref: 'AWS::Partition' }, '-', 'my-function']], }, }, Metadata: { 'aws:asset:path': 'new-path', }, }, }, }, }); // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).not.toBeUndefined(); expect(mock_sdk_1.mockLambdaClient).toHaveReceivedCommandWith(client_lambda_1.UpdateFunctionCodeCommand, { FunctionName: 'swa-my-function', S3Bucket: 'current-bucket', S3Key: 'new-key', }); }); (0, silent_1.silentTest)('can correctly reference AWS::URLSuffix in hotswappable changes', async () => { // GIVEN setup.setCurrentCfnStackTemplate({ Resources: { Func: { Type: 'AWS::Lambda::Function', Properties: { Code: { S3Bucket: 'current-bucket', S3Key: 'current-key', }, FunctionName: { 'Fn::Join': ['', ['my-function-', { Ref: 'AWS::URLSuffix' }, '-', { Ref: 'AWS::URLSuffix' }]], }, }, Metadata: { 'aws:asset:path': 'old-path', }, }, }, }); const cdkStackArtifact = setup.cdkStackArtifactOf({ template: { Resources: { Func: { Type: 'AWS::Lambda::Function', Properties: { Code: { S3Bucket: 'current-bucket', S3Key: 'new-key', }, FunctionName: { 'Fn::Join': ['', ['my-function-', { Ref: 'AWS::URLSuffix' }, '-', { Ref: 'AWS::URLSuffix' }]], }, }, Metadata: { 'aws:asset:path': 'new-path', }, }, }, }, }); // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).not.toBeUndefined(); expect(mock_sdk_1.mockLambdaClient).toHaveReceivedCommandWith(client_lambda_1.UpdateFunctionCodeCommand, { FunctionName: 'my-function-amazonaws.com-amazonaws.com', S3Bucket: 'current-bucket', S3Key: 'new-key', }); }); (0, silent_1.silentTest)('changing the type of a deployed resource always results in a full deployment for HOTSWAP and a noOp for HOTSWAP_ONLY', async () => { // GIVEN setup.setCurrentCfnStackTemplate({ Resources: { SharedLogicalId: { Type: 'AWS::Lambda::Function', Properties: { Code: { S3Bucket: 'current-bucket', S3Key: 'new-key', }, FunctionName: 'my-function', }, }, }, }); const cdkStackArtifact = setup.cdkStackArtifactOf({ template: { Resources: { SharedLogicalId: { Type: 'AWS::StepFunctions::StateMachine', Properties: { DefinitionString: '{ Prop: "new-value" }', StateMachineName: 'my-machine', }, }, }, }, }); if (hotswapMode === common_1.HotswapMode.FALL_BACK) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).toBeUndefined(); expect(mock_sdk_1.mockStepFunctionsClient).not.toHaveReceivedCommand(client_sfn_1.UpdateStateMachineCommand); expect(mock_sdk_1.mockLambdaClient).not.toHaveReceivedCommand(client_lambda_1.UpdateFunctionCodeCommand); } else if (hotswapMode === common_1.HotswapMode.HOTSWAP_ONLY) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).not.toBeUndefined(); expect(deployStackResult?.noOp).toEqual(true); expect(mock_sdk_1.mockStepFunctionsClient).not.toHaveReceivedCommand(client_sfn_1.UpdateStateMachineCommand); expect(mock_sdk_1.mockLambdaClient).not.toHaveReceivedCommand(client_lambda_1.UpdateFunctionCodeCommand); } }); (0, silent_1.silentTest)('A change to both a hotswappable resource and a stack output results in a full deployment for HOTSWAP and a hotswap deployment for HOTSWAP_ONLY', async () => { // GIVEN setup.setCurrentCfnStackTemplate({ Resources: { Func: { Type: 'AWS::Lambda::Function', Properties: { Code: { S3Bucket: 'current-bucket', S3Key: 'current-key', }, FunctionName: 'my-function', }, Metadata: { 'aws:asset:path': 'old-path', }, }, }, Outputs: { SomeOutput: { Value: 'old-value', }, }, }); const cdkStackArtifact = setup.cdkStackArtifactOf({ template: { Resources: { Func: { Type: 'AWS::Lambda::Function', Properties: { Code: { S3Bucket: 'current-bucket', S3Key: 'new-key', }, FunctionName: 'my-function', }, Metadata: { 'aws:asset:path': 'new-path', }, }, }, Outputs: { SomeOutput: { Value: 'new-value', }, }, }, }); if (hotswapMode === common_1.HotswapMode.FALL_BACK) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).toBeUndefined(); expect(mock_sdk_1.mockStepFunctionsClient).not.toHaveReceivedCommand(client_sfn_1.UpdateStateMachineCommand); expect(mock_sdk_1.mockLambdaClient).not.toHaveReceivedCommand(client_lambda_1.UpdateFunctionCodeCommand); } else if (hotswapMode === common_1.HotswapMode.HOTSWAP_ONLY) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).not.toBeUndefined(); expect(mock_sdk_1.mockLambdaClient).toHaveReceivedCommandWith(client_lambda_1.UpdateFunctionCodeCommand, { FunctionName: 'my-function', S3Bucket: 'current-bucket', S3Key: 'new-key', }); expect(mock_sdk_1.mockStepFunctionsClient).not.toHaveReceivedCommand(client_sfn_1.UpdateStateMachineCommand); } }); (0, silent_1.silentTest)('Multiple CfnEvaluationException will not cause unhandled rejections', async () => { // GIVEN setup.setCurrentCfnStackTemplate({ Resources: { Func1: { Type: 'AWS::Lambda::Function', Properties: { Code: { S3Bucket: 'current-bucket', S3Key: 'current-key', }, Environment: { key: 'old', }, FunctionName: 'my-function', }, Metadata: { 'aws:asset:path': 'old-path', }, }, Func2: { Type: 'AWS::Lambda::Function', Properties: { Code: { S3Bucket: 'current-bucket', S3Key: 'current-key', }, Environment: { key: 'old', }, FunctionName: 'my-function', }, Metadata: { 'aws:asset:path': 'old-path', }, }, }, }); const cdkStackArtifact = setup.cdkStackArtifactOf({ template: { Resources: { Func1: { Type: 'AWS::Lambda::Function', Properties: { Code: { S3Bucket: 'current-bucket', S3Key: 'current-key', }, Environment: { key: { Ref: 'ErrorResource' }, }, FunctionName: 'my-function', }, Metadata: { 'aws:asset:path': 'new-path', }, }, Func2: { Type: 'AWS::Lambda::Function', Properties: { Code: { S3Bucket: 'current-bucket', S3Key: 'current-key', }, Environment: { key: { Ref: 'ErrorResource' }, }, FunctionName: 'my-function', }, Metadata: { 'aws:asset:path': 'new-path', }, }, }, }, }); // WHEN const deployStackResult = hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN await expect(deployStackResult).rejects.toThrow(evaluate_cloudformation_template_1.CfnEvaluationException); expect(mock_sdk_1.mockStepFunctionsClient).not.toHaveReceivedCommand(client_sfn_1.UpdateStateMachineCommand); expect(mock_sdk_1.mockLambdaClient).not.toHaveReceivedCommand(client_lambda_1.UpdateFunctionCodeCommand); }); (0, silent_1.silentTest)('deleting a resource and making a hotswappable change results in full deployments for HOTSWAP and a hotswap deployment for HOTSWAP_ONLY', async () => { // GIVEN setup.setCurrentCfnStackTemplate({ Resources: { Machine: { Type: 'AWS::StepFunctions::StateMachine', }, Func: { Type: 'AWS::Lambda::Function', Properties: { Code: { S3Bucket: 'current-bucket', S3Key: 'current-key', }, FunctionName: 'my-function', }, Metadata: { 'aws:asset:path': 'old-path', }, }, }, }); const cdkStackArtifact = setup.cdkStackArtifactOf({ template: { Resources: { Func: { Type: 'AWS::Lambda::Function', Properties: { Code: { S3Bucket: 'current-bucket', S3Key: 'new-key', }, FunctionName: 'my-function', }, Metadata: { 'aws:asset:path': 'new-path', }, }, }, }, }); if (hotswapMode === common_1.HotswapMode.FALL_BACK) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).toBeUndefined(); expect(mock_sdk_1.mockStepFunctionsClient).not.toHaveReceivedCommand(client_sfn_1.UpdateStateMachineCommand); expect(mock_sdk_1.mockLambdaClient).not.toHaveReceivedCommand(client_lambda_1.UpdateFunctionCodeCommand); } else if (hotswapMode === common_1.HotswapMode.HOTSWAP_ONLY) { // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).not.toBeUndefined(); expect(mock_sdk_1.mockStepFunctionsClient).not.toHaveReceivedCommand(client_sfn_1.UpdateStateMachineCommand); expect(mock_sdk_1.mockLambdaClient).toHaveReceivedCommandWith(client_lambda_1.UpdateFunctionCodeCommand, { FunctionName: 'my-function', S3Bucket: 'current-bucket', S3Key: 'new-key', }); } }); (0, silent_1.silentTest)('can correctly reference Fn::ImportValue in hotswappable changes', async () => { // GIVEN mock_sdk_1.mockCloudFormationClient.on(client_cloudformation_1.ListExportsCommand).resolves({ Exports: [ { ExportingStackId: 'test-exporting-stack-id', Name: 'test-import', Value: 'new-key', }, ], }); setup.setCurrentCfnStackTemplate({ Resources: { Func: { Type: 'AWS::Lambda::Function', Properties: { Code: { S3Bucket: 'current-bucket', S3Key: 'old-key', }, FunctionName: 'swa-my-function', }, Metadata: { 'aws:asset:path': 'new-path', }, }, }, }); const cdkStackArtifact = setup.cdkStackArtifactOf({ template: { Resources: { Func: { Type: 'AWS::Lambda::Function', Properties: { Code: { S3Bucket: 'current-bucket', S3Key: { 'Fn::ImportValue': 'test-import', }, }, FunctionName: 'swa-my-function', }, Metadata: { 'aws:asset:path': 'new-path', }, }, }, }, }); // WHEN const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact); // THEN expect(deployStackResult).not.toBeUndefined(); expect(mock_sdk_1.mockLambdaClient).toHaveReceivedCommandWith(client_lambda_1.UpdateFunctionCodeCommand, { FunctionName: 'swa-my-function', S3Bucket: 'current-bucket', S3Key: 'new-key', }); }); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaG90c3dhcC1kZXBsb3ltZW50cy50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiaG90c3dhcC1kZXBsb3ltZW50cy50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsMEVBQW9FO0FBQ3BFLDBEQUFtRTtBQUNuRSxvREFBZ0U7QUFDaEUsd0dBQTJGO0FBQzNGLDREQUE4RDtBQUM5RCxrREFBbUg7QUFDbkgsOENBQStDO0FBQy9DLHVEQUF1RDtBQUV2RCxJQUFJLENBQUMsSUFBSSxDQUFDLHdCQUF3QixFQUFFLEdBQUcsRUFBRTtJQUN2QyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLHdCQUF3QixDQUFDLENBQUM7SUFFOUQsT0FBTztRQUNMLEdBQUcsUUFBUTtRQUNYLHdCQUF3QixFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7S0FDcEMsQ0FBQztBQUNKLENBQUMsQ0FBQyxDQUFDO0FBRUgsSUFBSSxzQkFBb0QsQ0FBQztBQUN6RCxJQUFJLEdBQVksQ0FBQztBQUVqQixVQUFVLENBQUMsR0FBRyxFQUFFO0lBQ2QsR0FBRyxHQUFHLElBQUksa0JBQU8sRUFBRSxDQUFDO0lBQ3BCLEdBQUcsQ0FBQyxZQUFZLEdBQUcsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUMxRCxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDckIsc0JBQXNCLEdBQUcsS0FBSyxDQUFDLGlCQUFpQixFQUFFLENBQUM7QUFDckQsQ0FBQyxDQUFDLENBQUM7QUFFSCxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsb0JBQVcsQ0FBQyxTQUFTLEVBQUUsb0JBQVcsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLFNBQVMsRUFBRSxDQUFDLFdBQVcsRUFBRSxFQUFFO0lBQzFGLElBQUEsbUJBQVUsRUFBQyxxRkFBcUYsRUFBRSxLQUFLLElBQUksRUFBRTtRQUMzRyxPQUFPO1FBQ1AsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLHNCQUFzQixDQUFDLG9CQUFvQixDQUN6RSxXQUFXLEVBQ1gsS0FBSyxDQUFDLGtCQUFrQixFQUFFLENBQzNCLENBQUM7UUFFRixPQUFPO1FBQ1AsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQzlDLE1BQU0sQ0FBQyxpQkFBaUIsRUFBRSxJQUFJLENBQUMsQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUM3QyxNQUFNLENBQUMsaUJBQWlCLEVBQUUsUUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM5RCxDQUFDLENBQUMsQ0FBQztJQUVILElBQUEsbUJBQVUsRUFDUixtSEFBbUgsRUFDbkgsS0FBSyxJQUFJLEVBQUU7UUFDVCxRQUFRO1FBQ1IsS0FBSyxDQUFDLDBCQUEwQixDQUFDO1lBQy9CLFNBQVMsRUFBRTtnQkFDVCxhQUFhLEVBQUU7b0JBQ2IsSUFBSSxFQUFFLG9DQUFvQztvQkFDMUMsVUFBVSxFQUFFO3dCQUNWLElBQUksRUFBRSxXQUFXO3FCQUNsQjtpQkFDRjthQUNGO1NBQ0YsQ0FBQyxDQUFDO1FBQ0gsTUFBTSxnQkFBZ0IsR0FBRyxLQUFLLENBQUMsa0JBQWtCLENBQUM7WUFDaEQsUUFBUSxFQUFFO2dCQUNSLFNBQVMsRUFBRTtvQkFDVCxhQUFhLEVBQUU7d0JBQ2IsSUFBSSxFQUFFLG9DQUFvQzt3QkFDMUMsVUFBVSxFQUFFOzRCQUNWLElBQUksRUFBRSxXQUFXO3lCQUNsQjtxQkFDRjtpQkFDRjthQUNGO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsSUFBSSxXQUFXLEtBQUssb0JBQVcsQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUMxQyxPQUFPO1lBQ1AsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLHNCQUFzQixDQUFDLG9CQUFvQixDQUFDLFdBQVcsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1lBRTNHLE9BQU87WUFDUCxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUMxQyxNQUFNLENBQUMsa0NBQXVCLENBQUMsQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMsc0NBQXlCLENBQUMsQ0FBQztZQUNyRixNQUFNLENBQUMsMkJBQWdCLENBQUMsQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMseUNBQXlCLENBQUMsQ0FBQztRQUNoRixDQUFDO2FBQU0sSUFBSSxXQUFXLEtBQUssb0JBQVcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUNwRCxPQUFPO1lBQ1AsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLHNCQUFzQixDQUFDLG9CQUFvQixDQUFDLFdBQVcsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1lBRTNHLE9BQU87WUFDUCxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDOUMsTUFBTSxDQUFDLGlCQUFpQixFQUFFLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM5QyxNQUFNLENBQUMsa0NBQXVCLENBQUMsQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMsc0NBQXlCLENBQUMsQ0FBQztZQUNyRixNQUFNLENBQUMsMkJBQWdCLENBQUMsQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMseUNBQXlCLENBQUMsQ0FBQztRQUNoRixDQUFDO0lBQ0gsQ0FBQyxDQUNGLENBQUM7SUFFRixJQUFBLG1CQUFVLEVBQ1IsK0lBQStJLEVBQy9JLEtBQUssSUFBSSxFQUFFO1FBQ1QsUUFBUTtRQUNSLEtBQUssQ0FBQywwQkFBMEIsQ0FBQztZQUMvQixTQUFTLEVBQUU7Z0JBQ1QsSUFBSSxFQUFFO29CQUNKLElBQUksRUFBRSx1QkFBdUI7b0JBQzdCLFVBQVUsRUFBRTt3QkFDVixJQUFJLEVBQUU7NEJBQ0osUUFBUSxFQUFFLGdCQUFnQjs0QkFDMUIsS0FBSyxFQUFFLGFBQWE7eUJBQ3JCO3dCQUNELFlBQVksRUFBRSxhQUFhO3FCQUM1QjtvQkFDRCxRQUFRLEVBQUU7d0JBQ1IsZ0JBQWdCLEVBQUUsVUFBVTtxQkFDN0I7aUJBQ0Y7Z0JBQ0QsYUFBYSxFQUFFO29CQUNiLElBQUksRUFBRSxvQ0FBb0M7b0JBQzFDLFVBQVUsRUFBRTt3QkFDVixJQUFJLEVBQUUsV0FBVztxQkFDbEI7aUJBQ0Y7YUFDRjtTQUNGLENBQUMsQ0FBQztRQUNILE1BQU0sZ0JBQWdCLEdBQUcsS0FBSyxDQUFDLGtCQUFrQixDQUFDO1lBQ2hELFFBQVEsRUFBRTtnQkFDUixTQUFTLEVBQUU7b0JBQ1QsSUFBSSxFQUFFO3dCQUNKLElBQUksRUFBRSx1QkFBdUI7d0JBQzdCLFVBQVUsRUFBRTs0QkFDVixJQUFJLEVBQUU7Z0NBQ0osUUFBUSxFQUFFLGdCQUFnQjtnQ0FDMUIsS0FBSyxFQUFFLFNBQVM7NkJBQ2pCOzRCQUNELFlBQVksRUFBRSxhQUFhO3lCQUM1Qjt3QkFDRCxRQUFRLEVBQUU7NEJBQ1IsZ0JBQWdCLEVBQUUsVUFBVTt5QkFDN0I7cUJBQ0Y7b0JBQ0QsYUFBYSxFQUFFO3dCQUNiLElBQUksRUFBRSxvQ0FBb0M7d0JBQzFDLFVBQVUsRUFBRTs0QkFDVixJQUFJLEVBQUUsV0FBVzt5QkFDbEI7cUJBQ0Y7aUJBQ0Y7YUFDRjtTQUNGLENBQUMsQ0FBQztRQUVILElBQUksV0FBVyxLQUFLLG9CQUFXLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDMUMsT0FBTztZQUNQLE1BQU0saUJBQWlCLEdBQUcsTUFBTSxzQkFBc0IsQ0FBQyxvQkFBb0IsQ0FBQyxXQUFXLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztZQUUzRyxPQUFPO1lBQ1AsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDMUMsTUFBTSxDQUFDLGtDQUF1QixDQUFDLENBQUMsR0FBRyxDQUFDLHFCQUFxQixDQUFDLHNDQUF5QixDQUFDLENBQUM7WUFDckYsTUFBTSxDQUFDLDJCQUFnQixDQUFDLENBQUMsR0FBRyxDQUFDLHFCQUFxQixDQUFDLHlDQUF5QixDQUFDLENBQUM7UUFDaEYsQ0FBQzthQUFNLElBQUksV0FBVyxLQUFLLG9CQUFXLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDcEQsT0FBTztZQUNQLE1BQU0saUJBQWlCLEdBQUcsTUFBTSxzQkFBc0IsQ0FBQyxvQkFBb0IsQ0FBQyxXQUFXLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztZQUUzRyxPQUFPO1lBQ1AsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQzlDLE1BQU0sQ0FBQywyQkFBZ0IsQ0FBQyxDQUFDLHlCQUF5QixDQUFDLHlDQUF5QixFQUFFO2dCQUM1RSxZQUFZLEVBQUUsYUFBYTtnQkFDM0IsUUFBUSxFQUFFLGdCQUFnQjtnQkFDMUIsS0FBSyxFQUFFLFNBQVM7YUFDakIsQ0FBQyxDQUFDO1lBQ0gsTUFBTSxDQUFDLGtDQUF1QixDQUFDLENBQUMsR0FBRyxDQUFDLHFCQUFxQixDQUFDLHNDQUF5QixDQUFDLENBQUM7UUFDdkYsQ0FBQztJQUNILENBQUMsQ0FDRixDQUFDO0lBRUYsSUFBQSxtQkFBVSxFQUFDLGdEQUFnRCxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ3RFLFFBQVE7UUFDUixLQUFLLENBQUMsMEJBQTBCLENBQUM7WUFDL0IsU0FBUyxFQUFFO2dCQUNULFFBQVEsRUFBRTtvQkFDUixJQUFJLEVBQUUsb0JBQW9CO29CQUMxQixVQUFVLEVBQUU7d0JBQ1YsSUFBSSxFQUFFLFdBQVc7cUJBQ2xCO2lCQUNGO2FBQ0Y7U0FDRixDQUFDLENBQUM7UUFDSCxNQUFNLGdCQUFnQixHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQztZQUNoRCxRQUFRLEVBQUU7Z0JBQ1IsU0FBUyxFQUFFO29CQUNULFFBQVEsRUFBRTt3QkFDUixJQUFJLEVBQUUsb0JBQW9CO3dCQUMxQixVQUFVLEVBQUU7NEJBQ1YsSUFBSSxFQUFFLFdBQVc7eUJBQ2xCO3FCQUNGO2lCQUNGO2FBQ0Y7U0FDRixDQUFDLENBQUM7UUFFSCxPQUFPO1FBQ1AsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLHNCQUFzQixDQUFDLG9CQUFvQixDQUFDLFdBQVcsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1FBRTNHLE9BQU87UUFDUCxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDOUMsTUFBTSxDQUFDLGlCQUFpQixFQUFFLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM5QyxNQUFNLENBQUMsa0NBQXVCLENBQUMsQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMsc0NBQXlCLENBQUMsQ0FBQztRQUNyRixNQUFNLENBQUMsMkJBQWdCLENBQUMsQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMseUNBQXlCLENBQUMsQ0FBQztJQUNoRixDQUFDLENBQUMsQ0FBQztJQUVILElBQUEsbUJBQVUsRUFBQyxxRkFBcUYsRUFBRSxLQUFLLElBQUksRUFBRTtRQUMzRyxRQUFRO1FBQ1IsS0FBSyxDQUFDLDBCQUEwQixDQUFDO1lBQy9CLFNBQVMsRUFBRTtnQkFDVCxPQUFPLEVBQUU7b0JBQ1AsSUFBSSxFQUFFLGtDQUFrQztpQkFDekM7YUFDRjtTQUNGLENBQUMsQ0FBQztRQUNILE1BQU0sZ0JBQWdCLEdBQUcsS0FBSyxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFFcEQsSUFBSSxXQUFXLEtBQUssb0JBQVcsQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUMxQyxPQUFPO1lBQ1AsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLHNCQUFzQixDQUFDLG9CQUFvQixDQUFDLFdBQVcsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1lBRTNHLE9BQU87WUFDUCxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUMxQyxNQUFNLENBQUMsa0NBQXVCLENBQUMsQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMsc0NBQXlCLENBQUMsQ0FBQztZQUNyRixNQUFNLENBQUMsMkJBQWdCLENBQUMsQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMseUNBQXlCLENBQUMsQ0FBQztRQUNoRixDQUFDO2FBQU0sSUFBSSxXQUFXLEtBQUssb0JBQVcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUNwRCxPQUFPO1lBQ1AsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLHNCQUFzQixDQUFDLG9CQUFvQixDQUFDLFdBQVcsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1lBRTNHLE9BQU87WUFDUCxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDOUMsTUFBTSxDQUFDLGlCQUFpQixFQUFFLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM5QyxNQUFNLENBQUMsa0NBQXVCLENBQUMsQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMsc0NBQXlCLENBQUMsQ0FBQztZQUNyRixNQUFNLENBQUMsMkJBQWdCLENBQUMsQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMseUNBQXlCLENBQUMsQ0FBQztRQUNoRixDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFBLG1CQUFVLEVBQUMsZ0VBQWdFLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDdEYsUUFBUTtRQUNSLEtBQUssQ0FBQywwQkFBMEIsQ0FBQztZQUMvQixTQUFTLEVBQUU7Z0JBQ1QsSUFBSSxFQUFFO29CQUNKLElBQUksRUFBRSx1QkFBdUI7b0JBQzdCLFVBQVUsRUFBRTt3QkFDVixJQUFJLEVBQUU7NEJBQ0osUUFBUSxFQUFFLGdCQUFnQjs0QkFDMUIsS0FBSyxFQUFFLGFBQWE7eUJBQ3JCO3dCQUNELFlBQVksRUFBRTs0QkFDWixVQUFVLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxnQkFBZ0IsRUFBRSxFQUFFLEdBQUcsRUFBRSxhQUFhLENBQUMsQ0FBQzt5QkFDbEU7cUJBQ0Y7b0JBQ0QsUUFBUSxFQUFFO3dCQUNSLGdCQUFnQixFQUFFLFVBQVU7cUJBQzdCO2lCQUNGO2FBQ0Y7U0FDRixDQUFDLENBQUM7UUFDSCxNQUFNLGdCQUFnQixHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQztZQUNoRCxRQUFRLEVBQUU7Z0JBQ1IsU0FBUyxFQUFFO29CQUNULElBQUksRUFBRTt3QkFDSixJQUFJLEVBQUUsdUJBQXVCO3dCQUM3QixVQUFVLEVBQUU7NEJBQ1YsSUFBSSxFQUFFO2dDQUNKLFFBQVEsRUFBRSxnQkFBZ0I7Z0NBQzFCLEtBQUssRUFBRSxTQUFTOzZCQUNqQjs0QkFDRCxZQUFZLEVBQUU7Z0NBQ1osVUFBVSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsZ0JBQWdCLEVBQUUsRUFBRSxHQUFHLEVBQUUsYUFBYSxDQUFDLENBQUM7NkJBQ2xFO3lCQUNGO3dCQUNELFFBQVEsRUFBRTs0QkFDUixnQkFBZ0IsRUFBRSxVQUFVO3lCQUM3QjtxQkFDRjtpQkFDRjthQUNGO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsT0FBTztRQUNQLE1BQU0saUJBQWlCLEdBQUcsTUFBTSxzQkFBc0IsQ0FBQyxvQkFBb0IsQ0FBQyxXQUFXLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztRQUUzRyxPQUFPO1FBQ1AsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQzlDLE1BQU0sQ0FBQywyQkFBZ0IsQ0FBQyxDQUFDLHlCQUF5QixDQUFDLHlDQUF5QixFQUFFO1lBQzVFLFlBQVksRUFBRSxpQkFBaUI7WUFDL0IsUUFBUSxFQUFFLGdCQUFnQjtZQUMxQixLQUFLLEVBQUUsU0FBUztTQUNqQixDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILElBQUEsbUJBQVUsRUFBQyxnRUFBZ0UsRUFBRSxLQUFLLElBQUksRUFBRTtRQUN0RixRQUFRO1FBQ1IsS0FBSyxDQUFDLDBCQUEwQixDQUFDO1lBQy9CLFNBQVMsRUFBRTtnQkFDVCxJQUFJLEVBQUU7b0JBQ0osSUFBSSxFQUFFLHVCQUF1QjtvQkFDN0IsVUFBVSxFQUFFO3dCQUNWLElBQUksRUFBRTs0QkFDSixRQUFRLEVBQUUsZ0JBQWdCOzRCQUMxQixLQUFLLEVBQUUsYUFBYTt5QkFDckI7d0JBQ0QsWUFBWSxFQUFFOzRCQUNaLFVBQVUsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLGNBQWMsRUFBRSxFQUFFLEdBQUcsRUFBRSxnQkFBZ0IsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLEdBQUcsRUFBRSxnQkFBZ0IsRUFBRSxDQUFDLENBQUM7eUJBQzlGO3FCQUNGO29CQUNELFFBQVEsRUFBRTt3QkFDUixnQkFBZ0IsRUFBRSxVQUFVO3FCQUM3QjtpQkFDRjthQUNGO1NBQ0YsQ0FBQyxDQUFDO1FBQ0gsTUFBTSxnQkFBZ0IsR0FBRyxLQUFLLENBQUMsa0JBQWtCLENBQUM7WUFDaEQsUUFBUSxFQUFFO2dCQUNSLFNBQVMsRUFBRTtvQkFDVCxJQUFJLEVBQUU7d0JBQ0osSUFBSSxFQUFFLHVCQUF1Qjt3QkFDN0IsVUFBVSxFQUFFOzRCQUNWLElBQUksRUFBRTtnQ0FDSixRQUFRLEVBQUUsZ0JBQWdCO2dDQUMxQixLQUFLLEVBQUUsU0FBUzs2QkFDakI7NEJBQ0QsWUFBWSxFQUFFO2dDQUNaLFVBQVUsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLGNBQWMsRUFBRSxFQUFFLEdBQUcsRUFBRSxnQkFBZ0IsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLEdBQUcsRUFBRSxnQkFBZ0IsRUFBRSxDQUFDLENBQUM7NkJBQzlGO3lCQUNGO3dCQUNELFFBQVEsRUFBRTs0QkFDUixnQkFBZ0IsRUFBRSxVQUFVO3lCQUM3QjtxQkFDRjtpQkFDRjthQUNGO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsT0FBTztRQUNQLE1BQU0saUJBQWlCLEdBQUcsTUFBTSxzQkFBc0IsQ0FBQyxvQkFBb0IsQ0FBQyxXQUFXLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztRQUUzRyxPQUFPO1FBQ1AsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQzlDLE1BQU0sQ0FBQywyQkFBZ0IsQ0FBQyxDQUFDLHlCQUF5QixDQUFDLHlDQUF5QixFQUFFO1lBQzVFLFlBQVksRUFBRSx5Q0FBeUM7WUFDdkQsUUFBUSxFQUFFLGdCQUFnQjtZQUMxQixLQUFLLEVBQUUsU0FBUztTQUNqQixDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILElBQUEsbUJBQVUsRUFDUixzSEFBc0gsRUFDdEgsS0FBSyxJQUFJLEVBQUU7UUFDVCxRQUFRO1FBQ1IsS0FBSyxDQUFDLDBCQUEwQixDQUFDO1lBQy9CLFNBQVMsRUFBRTtnQkFDVCxlQUFlLEVBQUU7b0JBQ2YsSUFBSSxFQUFFLHVCQUF1QjtvQkFDN0IsVUFBVSxFQUFFO3dCQUNWLElBQUksRUFBRTs0QkFDSixRQUFRLEVBQUUsZ0JBQWdCOzRCQUMxQixLQUFLLEVBQUUsU0FBUzt5QkFDakI7d0JBQ0QsWUFBWSxFQUFFLGFBQWE7cUJBQzVCO2lCQUNGO2FBQ0Y7U0FDRixDQUFDLENBQUM7UUFDSCxNQUFNLGdCQUFnQixHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQztZQUNoRCxRQUFRLEVBQUU7Z0JBQ1IsU0FBUyxFQUFFO29CQUNULGVBQWUsRUFBRTt3QkFDZixJQUFJLEVBQUUsa0NBQWtDO3dCQUN4QyxVQUFVLEVBQUU7NEJBQ1YsZ0JBQWdCLEVBQUUsdUJBQXVCOzRCQUN6QyxnQkFBZ0IsRUFBRSxZQUFZO3lCQUMvQjtxQkFDRjtpQkFDRjthQUNGO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsSUFBSSxXQUFXLEtBQUssb0JBQVcsQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUMxQyxPQUFPO1lBQ1AsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLHNCQUFzQixDQUFDLG9CQUFvQixDQUFDLFdBQVcsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1lBRTNHLE9BQU87WUFDUCxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUMxQyxNQUFNLENBQUMsa0NBQXVCLENBQUMsQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMsc0NBQXlCLENBQUMsQ0FBQztZQUNyRixNQUFNLENBQUMsMkJBQWdCLENBQUMsQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMseUNBQXlCLENBQUMsQ0FBQztRQUNoRixDQUFDO2FBQU0sSUFBSSxXQUFXLEtBQUssb0JBQVcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUNwRCxPQUFPO1lBQ1AsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLHNCQUFzQixDQUFDLG9CQUFvQixDQUFDLFdBQVcsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1lBRTNHLE9BQU87WUFDUCxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDOUMsTUFBTSxDQUFDLGlCQUFpQixFQUFFLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM5QyxNQUFNLENBQUMsa0NBQXVCLENBQUMsQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMsc0NBQXlCLENBQUMsQ0FBQztZQUNyRixNQUFNLENBQUMsMkJBQWdCLENBQUMsQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMseUNBQXlCLENBQUMsQ0FBQztRQUNoRixDQUFDO0lBQ0gsQ0FBQyxDQUNGLENBQUM7SUFFRixJQUFBLG1CQUFVLEVBQ1IsZ0pBQWdKLEVBQ2hKLEtBQUssSUFBSSxFQUFFO1FBQ1QsUUFBUTtRQUNSLEtBQUssQ0FBQywwQkFBMEIsQ0FBQztZQUMvQixTQUFTLEVBQUU7Z0JBQ1QsSUFBSSxFQUFFO29CQUNKLElBQUksRUFBRSx1QkFBdUI7b0JBQzdCLFVBQVUsRUFBRTt3QkFDVixJQUFJLEVBQUU7NEJBQ0osUUFBUSxFQUFFLGdCQUFnQjs0QkFDMUIsS0FBSyxFQUFFLGFBQWE7eUJBQ3JCO3dCQUNELFlBQVksRUFBRSxhQUFhO3FCQUM1QjtvQkFDRCxRQUFRLEVBQUU7d0JBQ1IsZ0JBQWdCLEVBQUUsVUFBVTtxQkFDN0I7aUJBQ0Y7YUFDRjtZQUNELE9BQU8sRUFBRTtnQkFDUCxVQUFVLEVBQUU7b0JBQ1YsS0FBSyxFQUFFLFdBQVc7aUJBQ25CO2FBQ0Y7U0FDRixDQUFDLENBQUM7UUFDSCxNQUFNLGdCQUFnQixHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQztZQUNoRCxRQUFRLEVBQUU7Z0JBQ1IsU0FBUyxFQUFFO29CQUNULElBQUksRUFBRTt3QkFDSixJQUFJLEVBQUUsdUJBQXVCO3dCQUM3QixVQUFVLEVBQUU7NEJBQ1YsSUFBSSxFQUFFO2dDQUNKLFFBQVEsRUFBRSxnQkFBZ0I7Z0NBQzFCLEtBQUssRUFBRSxTQUFTOzZCQUNqQjs0QkFDRCxZQUFZLEVBQUUsYUFBYTt5QkFDNUI7d0JBQ0QsUUFBUSxFQUFFOzRCQUNSLGdCQUFnQixFQUFFLFVBQVU7eUJBQzdCO3FCQUNGO2lCQUNGO2dCQUNELE9BQU8sRUFBRTtvQkFDUCxVQUFVLEVBQUU7d0JBQ1YsS0FBSyxFQUFFLFdBQVc7cUJBQ25CO2lCQUNGO2FBQ0Y7U0FDRixDQUFDLENBQUM7UUFFSCxJQUFJLFdBQVcsS0FBSyxvQkFBVyxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQzFDLE9BQU87WUFDUCxNQUFNLGlCQUFpQixHQUFHLE1BQU0sc0JBQXNCLENBQUMsb0JBQW9CLENBQUMsV0FBVyxFQUFFLGdCQUFnQixDQUFDLENBQUM7WUFFM0csT0FBTztZQUNQLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQzFDLE1BQU0sQ0FBQyxrQ0FBdUIsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxxQkFBcUIsQ0FBQyxzQ0FBeUIsQ0FBQyxDQUFDO1lBQ3JGLE1BQU0sQ0FBQywyQkFBZ0IsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxxQkFBcUIsQ0FBQyx5Q0FBeUIsQ0FBQyxDQUFDO1FBQ2hGLENBQUM7YUFBTSxJQUFJLFdBQVcsS0FBSyxvQkFBVyxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3BELE9BQU87WUFDUCxNQUFNLGlCQUFpQixHQUFHLE1BQU0sc0JBQXNCLENBQUMsb0JBQW9CLENBQUMsV0FBVyxFQUFFLGdCQUFnQixDQUFDLENBQUM7WUFFM0csT0FBTztZQUNQLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUM5QyxNQUFNLENBQUMsMkJBQWdCLENBQUMsQ0FBQyx5QkFBeUIsQ0FBQyx5Q0FBeUIsRUFBRTtnQkFDNUUsWUFBWSxFQUFFLGFBQWE7Z0JBQzNCLFFBQVEsRUFBRSxnQkFBZ0I7Z0JBQzFCLEtBQUssRUFBRSxTQUFTO2FBQ2pCLENBQUMsQ0FBQztZQUNILE1BQU0sQ0FBQyxrQ0FBdUIsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxxQkFBcUIsQ0FBQyxzQ0FBeUIsQ0FBQyxDQUFDO1FBQ3ZGLENBQUM7SUFDSCxDQUFDLENBQ0YsQ0FBQztJQUVGLElBQUEsbUJBQVUsRUFBQyxxRUFBcUUsRUFBRSxLQUFLLElBQUksRUFBRTtRQUMzRixRQUFRO1FBQ1IsS0FBSyxDQUFDLDBCQUEwQixDQUFDO1lBQy9CLFNBQVMsRUFBRTtnQkFDVCxLQUFLLEVBQUU7b0JBQ0wsSUFBSSxFQUFFLHVCQUF1QjtvQkFDN0IsVUFBVSxFQUFFO3dCQUNWLElBQUksRUFBRTs0QkFDSixRQUFRLEVBQUUsZ0JBQWdCOzRCQUMxQixLQUFLLEVBQUUsYUFBYTt5QkFDckI7d0JBQ0QsV0FBVyxFQUFFOzRCQUNYLEdBQUcsRUFBRSxLQUFLO3lCQUNYO3dCQUNELFlBQVksRUFBRSxhQUFhO3FCQUM1QjtvQkFDRCxRQUFRLEVBQUU7d0JBQ1IsZ0JBQWdCLEVBQUUsVUFBVTtxQkFDN0I7aUJBQ0Y7Z0JBQ0QsS0FBSyxFQUFFO29CQUNMLElBQUksRUFBRSx1QkFBdUI7b0JBQzdCLFVBQVUsRUFBRTt3QkFDVixJQUFJLEVBQUU7NEJBQ0osUUFBUSxFQUFFLGdCQUFnQjs0QkFDMUIsS0FBSyxFQUFFLGFBQWE7eUJBQ3JCO3dCQUNELFdBQVcsRUFBRTs0QkFDWCxHQUFHLEVBQUUsS0FBSzt5QkFDWDt3QkFDRCxZQUFZLEVBQUUsYUFBYTtxQkFDNUI7b0JBQ0QsUUFBUSxFQUFFO3dCQUNSLGdCQUFnQixFQUFFLFVBQVU7cUJBQzdCO2lCQUNGO2FBQ0Y7U0FDRixDQUFDLENBQUM7UUFDSCxNQUFNLGdCQUFnQixHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQztZQUNoRCxRQUFRLEVBQUU7Z0JBQ1IsU0FBUyxFQUFFO29CQUNULEtBQUssRUFBRTt3QkFDTCxJQUFJLEVBQUUsdUJBQXVCO3dCQUM3QixVQUFVLEVBQUU7NEJBQ1YsSUFBSSxFQUFFO2dDQUNKLFFBQVEsRUFBRSxnQkFBZ0I7Z0NBQzFCLEtBQUssRUFBRSxhQUFhOzZCQUNyQjs0QkFDRCxXQUFXLEVBQUU7Z0NBQ1gsR0FBRyxFQUFFLEVBQUUsR0FBRyxFQUFFLGVBQWUsRUFBRTs2QkFDOUI7NEJBQ0QsWUFBWSxFQUFFLGFBQWE7eUJBQzVCO3dCQUNELFFBQVEsRUFBRTs0QkFDUixnQkFBZ0IsRUFBRSxVQUFVO3lCQUM3QjtxQkFDRjtvQkFDRCxLQUFLLEVBQUU7d0JBQ0wsSUFBSSxFQUFFLHVCQUF1Qjt3QkFDN0IsVUFBVSxFQUFFOzRCQUNWLElBQUksRUFBRTtnQ0FDSixRQUFRLEVBQUUsZ0JBQWdCO2dDQUMxQixLQUFLLEVBQUUsYUFBYTs2QkFDckI7NEJBQ0QsV0FBVyxFQUFFO2dDQUNYLEdBQUcsRUFBRSxFQUFFLEdBQUcsRUFBRSxlQUFlLEVBQUU7NkJBQzlCOzRCQUNELFlBQVksRUFBRSxhQUFhO3lCQUM1Qjt3QkFDRCxRQUFRLEVBQUU7NEJBQ1IsZ0JBQWdCLEVBQUUsVUFBVTt5QkFDN0I7cUJBQ0Y7aUJBQ0Y7YUFDRjtTQUNGLENBQUMsQ0FBQztRQUVILE9BQU87UUFDUCxNQUFNLGlCQUFpQixHQUFHLHNCQUFzQixDQUFDLG9CQUFvQixDQUFDLFdBQVcsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1FBRXJHLE9BQU87UUFDUCxNQUFNLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMseURBQXNCLENBQUMsQ0FBQztRQUN4RSxNQUFNLENBQUMsa0NBQXVCLENBQUMsQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMsc0NBQXlCLENBQUMsQ0FBQztRQUNyRixNQUFNLENBQUMsMkJBQWdCLENBQUMsQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMseUNBQXlCLENBQUMsQ0FBQztJQUNoRixDQUFDLENBQUMsQ0FBQztJQUVILElBQUEsbUJBQVUsRUFDUix3SUFBd0ksRUFDeEksS0FBSyxJQUFJLEVBQUU7UUFDVCxRQUFRO1FBQ1IsS0FBSyxDQUFDLDBCQUEwQixDQUFDO1lBQy9CLFNBQVMsRUFBRTtnQkFDVCxPQUFPLEVBQUU7b0JBQ1AsSUFBSSxFQUFFLGtDQUFrQztpQkFDekM7Z0JBQ0QsSUFBSSxFQUFFO29CQUNKLElBQUksRUFBRSx1QkFBdUI7b0JBQzdCLFVBQVUsRUFBRTt3QkFDVixJQUFJLEVBQUU7NEJBQ0osUUFBUSxFQUFFLGdCQUFnQjs0QkFDMUIsS0FBSyxFQUFFLGFBQWE7eUJBQ3JCO3dCQUNELFlBQVksRUFBRSxhQUFhO3FCQUM1QjtvQkFDRCxRQUFRLEVBQUU7d0JBQ1IsZ0JBQWdCLEVBQUUsVUFBVTtxQkFDN0I7aUJBQ0Y7YUFDRjtTQUNGLENBQUMsQ0FBQztRQUNILE1BQU0sZ0JBQWdCLEdBQUcsS0FBSyxDQUFDLGtCQUFrQixDQUFDO1lBQ2hELFFBQVEsRUFBRTtnQkFDUixTQUFTLEVBQUU7b0JBQ1QsSUFBSSxFQUFFO3dCQUNKLElBQUksRUFBRSx1QkFBdUI7d0JBQzdCLFVBQVUsRUFBRTs0QkFDVixJQUFJLEVBQUU7Z0NBQ0osUUFBUSxFQUFFLGdCQUFnQjtnQ0FDMUIsS0FBSyxFQUFFLFNBQVM7NkJBQ2pCOzRCQUNELFlBQVksRUFBRSxhQUFhO3lCQUM1Qjt3QkFDRCxRQUFRLEVBQUU7NEJBQ1IsZ0JBQWdCLEVBQUUsVUFBVTt5QkFDN0I7cUJBQ0Y7aUJBQ0Y7YUFDRjtTQUNGLENBQUMsQ0FBQztRQUVILElBQUksV0FBVyxLQUFLLG9CQUFXLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDMUMsT0FBTztZQUNQLE1BQU0saUJBQWlCLEdBQUcsTUFBTSxzQkFBc0IsQ0FBQyxvQkFBb0IsQ0FBQyxXQUFXLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztZQUUzRyxPQUFPO1lBQ1AsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDMUMsTUFBTSxDQUFDLGtDQUF1QixDQUFDLENBQUMsR0FBRyxDQUFDLHFCQUFxQixDQUFDLHNDQUF5QixDQUFDLENBQUM7WUFDckYsTUFBTSxDQUFDLDJCQUFnQixDQUFDLENBQUMsR0FBRyxDQUFDLHFCQUFxQixDQUFDLHlDQUF5QixDQUFDLENBQUM7UUFDaEYsQ0FBQzthQUFNLElBQUksV0FBVyxLQUFLLG9CQUFXLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDcEQsT0FBTztZQUNQLE1BQU0saUJBQWlCLEdBQUcsTUFBTSxzQkFBc0IsQ0FBQyxvQkFBb0IsQ0FBQyxXQUFXLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztZQUUzRyxPQUFPO1lBQ1AsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQzlDLE1BQU0sQ0FBQyxrQ0FBdUIsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxxQkFBcUIsQ0FBQyxzQ0FBeUIsQ0FBQyxDQUFDO1lBQ3JGLE1BQU0sQ0FBQywyQkFBZ0IsQ0FBQyxDQUFDLHlCQUF5QixDQUFDLHlDQUF5QixFQUFFO2dCQUM1RSxZQUFZLEVBQUUsYUFBYTtnQkFDM0IsUUFBUSxFQUFFLGdCQUFnQjtnQkFDMUIsS0FBSyxFQUFFLFNBQVM7YUFDakIsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztJQUNILENBQUMsQ0FDRixDQUFDO0lBRUYsSUFBQSxtQkFBVSxFQUFDLGlFQUFpRSxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ3ZGLFFBQVE7UUFDUixtQ0FBd0IsQ0FBQyxFQUFFLENBQUMsMENBQWtCLENBQUMsQ0FBQyxRQUFRLENBQUM7WUFDdkQsT0FBTyxFQUFFO2dCQUNQO29CQUNFLGdCQUFnQixFQUFFLHlCQUF5QjtvQkFDM0MsSUFBSSxFQUFFLGFBQWE7b0JBQ25CLEtBQUssRUFBRSxTQUFTO2lCQUNqQjthQUNGO1NBQ0YsQ0FBQyxDQUFDO1FBQ0gsS0FBSyxDQUFDLDBCQUEwQixDQUFDO1lBQy9CLFNBQVMsRUFBRTtnQkFDVCxJQUFJLEVBQUU7b0JBQ0osSUFBSSxFQUFFLHVCQUF1QjtvQkFDN0IsVUFBVSxFQUFFO3dCQUNWLElBQUksRUFBRTs0QkFDSixRQUFRLEVBQUUsZ0JBQWdCOzRCQUMxQixLQUFLLEVBQUUsU0FBUzt5QkFDakI7d0JBQ0QsWUFBWSxFQUFFLGlCQUFpQjtxQkFDaEM7b0JBQ0QsUUFBUSxFQUFFO3dCQUNSLGdCQUFnQixFQUFFLFVBQVU7cUJBQzdCO2lCQUNGO2FBQ0Y7U0FDRixDQUFDLENBQUM7UUFDSCxNQUFNLGdCQUFnQixHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQztZQUNoRCxRQUFRLEVBQUU7Z0JBQ1IsU0FBUyxFQUFFO29CQUNULElBQUksRUFBRTt3QkFDSixJQUFJLEVBQUUsdUJBQXVCO3dCQUM3QixVQUFVLEVBQUU7NEJBQ1YsSUFBSSxFQUFFO2dDQUNKLFFBQVEsRUFBRSxnQkFBZ0I7Z0NBQzFCLEtBQUssRUFBRTtvQ0FDTCxpQkFBaUIsRUFBRSxhQUFhO2lDQUNqQzs2QkFDRjs0QkFDRCxZQUFZLEVBQUUsaUJBQWlCO3lCQUNoQzt3QkFDRCxRQUFRLEVBQUU7NEJBQ1IsZ0JBQWdCLEVBQUUsVUFBVTt5QkFDN0I7cUJBQ0Y7aUJBQ0Y7YUFDRjtTQUNGLENBQUMsQ0FBQztRQUVILE9BQU87UUFDUCxNQUFNLGlCQUFpQixHQUFHLE1BQU0sc0JBQXNCLENBQUMsb0JBQW9CLENBQUMsV0FBVyxFQUFFLGdCQUFnQixDQUFDLENBQUM7UUFFM0csT0FBTztRQUNQLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUM5QyxNQUFNLENBQUMsMkJBQWdCLENBQUMsQ0FBQyx5QkFBeUIsQ0FBQyx5Q0FBeUIsRUFBRTtZQUM1RSxZQUFZLEVBQUUsaUJBQWlCO1lBQy9CLFFBQVEsRUFBRSxnQkFBZ0I7WUFDMUIsS0FBSyxFQUFFLFNBQVM7U0FDakIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IExpc3RFeHBvcnRzQ29tbWFuZCB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1jbG91ZGZvcm1hdGlvbic7XG5pbXBvcnQgeyBVcGRhdGVGdW5jdGlvbkNvZGVDb21tYW5kIH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWxhbWJkYSc7XG5pbXBvcnQgeyBVcGRhdGVTdGF0ZU1hY2hpbmVDb21tYW5kIH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LXNmbic7XG5pbXBvcnQgeyBDZm5FdmFsdWF0aW9uRXhjZXB0aW9uIH0gZnJvbSAnLi4vLi4vLi4vbGliL2FwaS9ldmFsdWF0ZS1jbG91ZGZvcm1hdGlvbi10ZW1wbGF0ZSc7XG5pbXBvcnQgeyBIb3Rzd2FwTW9kZSB9IGZyb20gJy4uLy4uLy4uL2xpYi9hcGkvaG90c3dhcC9jb21tb24nO1xuaW1wb3J0IHsgTW9ja1NkaywgbW9ja0Nsb3VkRm9ybWF0aW9uQ2xpZW50LCBtb2NrTGFtYmRhQ2xpZW50LCBtb2NrU3RlcEZ1bmN0aW9uc0NsaWVudCB9IGZyb20gJy4uLy4uL3V0aWwvbW9jay1zZGsnO1xuaW1wb3J0IHsgc2lsZW50VGVzdCB9IGZyb20gJy4uLy4uL3V0aWwvc2lsZW50JztcbmltcG9ydCAqIGFzIHNldHVwIGZyb20gJy4uL2hvdHN3YXAvaG90c3dhcC10ZXN0LXNldHVwJztcblxuamVzdC5tb2NrKCdAYXdzLXNkay9jbGllbnQtbGFtYmRhJywgKCkgPT4ge1xuICBjb25zdCBvcmlnaW5hbCA9IGplc3QucmVxdWlyZUFjdHVhbCgnQGF3cy1zZGsvY2xpZW50LWxhbWJkYScpO1xuXG4gIHJldHVybiB7XG4gICAgLi4ub3JpZ2luYWwsXG4gICAgd2FpdFVudGlsRnVuY3Rpb25VcGRhdGVkOiBqZXN0LmZuKCksXG4gIH07XG59KTtcblxubGV0IGhvdHN3YXBNb2NrU2RrUHJvdmlkZXI6IHNldHVwLkhvdHN3YXBNb2NrU2RrUHJvdmlkZXI7XG5sZXQgc2RrOiBNb2NrU2RrO1xuXG5iZWZvcmVFYWNoKCgpID0+IHtcbiAgc2RrID0gbmV3IE1vY2tTZGsoKTtcbiAgc2RrLmdldFVybFN1ZmZpeCA9ICgpID0+IFByb21pc2UucmVzb2x2ZSgnYW1hem9uYXdzLmNvbScpO1xuICBqZXN0LnJlc2V0QWxsTW9ja3MoKTtcbiAgaG90c3dhcE1vY2tTZGtQcm92aWRlciA9IHNldHVwLnNldHVwSG90c3dhcFRlc3RzKCk7XG59KTtcblxuZGVzY3JpYmUuZWFjaChbSG90c3dhcE1vZGUuRkFMTF9CQUNLLCBIb3Rzd2FwTW9kZS5IT1RTV0FQX09OTFldKSgnJXAgbW9kZScsIChob3Rzd2FwTW9kZSkgPT4ge1xuICBzaWxlbnRUZXN0KCdyZXR1cm5zIGEgZGVwbG95U3RhY2tSZXN1bHQgd2l0aCBub09wPXRydWUgd2hlbiBpdCByZWNlaXZlcyBhbiBlbXB0eSBzZXQgb2YgY2hhbmdlcycsIGFzeW5jICgpID0+IHtcbiAgICAvLyBXSEVOXG4gICAgY29uc3QgZGVwbG95U3RhY2tSZXN1bHQgPSBhd2FpdCBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyLnRyeUhvdHN3YXBEZXBsb3ltZW50KFxuICAgICAgaG90c3dhcE1vZGUsXG4gICAgICBzZXR1cC5jZGtTdGFja0FydGlmYWN0T2YoKSxcbiAgICApO1xuXG4gICAgLy8gVEhFTlxuICAgIGV4cGVjdChkZXBsb3lTdGFja1Jlc3VsdCkubm90LnRvQmVVbmRlZmluZWQoKTtcbiAgICBleHBlY3QoZGVwbG95U3RhY2tSZXN1bHQ/Lm5vT3ApLnRvQmVUcnV0aHkoKTtcbiAgICBleHBlY3QoZGVwbG95U3RhY2tSZXN1bHQ/LnN0YWNrQXJuKS50b0VxdWFsKHNldHVwLlNUQUNLX0lEKTtcbiAgfSk7XG5cbiAgc2lsZ