filestack-js
Version:
Official JavaScript library for Filestack
354 lines (352 loc) • 43.7 kB
JavaScript
/*
* Copyright (c) 2018 by Filestack.
* Some rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Copyright (c) 2018 by Filestack.
* Some rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { __awaiter, __generator } from "tslib";
import { retrieve, remove, metadata, download } from './file';
import { FsRequest } from './../request';
import { config } from './../../config';
jest.mock('./../request');
// jest.mock('./../filelink');
var mockedSession = {
apikey: 'fakeApikey',
urls: Object.assign({}, config.urls, {
cdnUrl: 'fakeUrl',
fileApiUrl: 'fakeApiUrl',
uploadApiUrl: 'fakeUploadApiUrl',
cloudApiUrl: 'fakeCloudApiUrl',
pickerUrl: 'fakePickerUrl',
}),
};
describe('FileAPI', function () {
describe('Metadata', function () {
it('should call correct metadata without options', function () { return __awaiter(void 0, void 0, void 0, function () {
var methodMocked, resp;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
methodMocked = jest.fn(function () { return Promise.resolve({ data: {} }); });
// @ts-ignore
FsRequest.get.mockImplementation(methodMocked);
return [4 /*yield*/, metadata(mockedSession, 'fakeHandle')];
case 1:
resp = _a.sent();
expect(resp).toEqual({ handle: 'fakeHandle' });
expect(methodMocked).toHaveBeenLastCalledWith('fakeApiUrl/fakeHandle/metadata', { params: {}, filestackHeaders: false });
return [2 /*return*/];
}
});
}); });
it('should call correct metadata with options', function () { return __awaiter(void 0, void 0, void 0, function () {
var methodMocked, resp;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
methodMocked = jest.fn(function () { return Promise.resolve({ data: {} }); });
// @ts-ignore
FsRequest.get.mockImplementation(methodMocked);
return [4 /*yield*/, metadata(mockedSession, 'fakeHandle', { size: true })];
case 1:
resp = _a.sent();
expect(resp).toEqual({ handle: 'fakeHandle' });
expect(methodMocked).toHaveBeenLastCalledWith('fakeApiUrl/fakeHandle/metadata', { params: { size: true }, filestackHeaders: false });
return [2 /*return*/];
}
});
}); });
it('should throw on wrong option', function () { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
// @ts-ignore
return [2 /*return*/, expect(function () { return metadata(mockedSession, 'fakekey', { bla: 123 }); }).toThrowError('Invalid metadata params')];
});
}); });
it('should throw an error on empty handle', function () {
return expect(function () { return metadata(mockedSession); }).toThrowError();
});
it('should respect provided security options', function () { return __awaiter(void 0, void 0, void 0, function () {
var fakeSecurity, resp;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
fakeSecurity = {
signature: 'fakeS',
policy: 'fakeP',
};
// @ts-ignore
FsRequest.get.mockImplementation(function () { return Promise.resolve({ data: {} }); });
return [4 /*yield*/, metadata(mockedSession, 'fakeHandle', {}, fakeSecurity)];
case 1:
resp = _a.sent();
expect(resp).toEqual({ handle: 'fakeHandle' });
return [2 /*return*/];
}
});
}); });
});
describe('Download', function () {
it('should return buffer on download request', function () { return __awaiter(void 0, void 0, void 0, function () {
var testResp, methodMocked, resp;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
testResp = Buffer.from('123');
methodMocked = jest.fn(function () { return Promise.resolve(testResp); });
// @ts-ignore
FsRequest.dispatch.mockImplementation(methodMocked);
return [4 /*yield*/, download(mockedSession, 'gNDNCDWNTKqoGFISdd2A')];
case 1:
resp = _a.sent();
expect(resp).toEqual(testResp);
return [2 /*return*/];
}
});
}); });
});
describe('Remove', function () {
it('should call remove', function () { return __awaiter(void 0, void 0, void 0, function () {
var deleteMocked, resp;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
deleteMocked = jest.fn(function () { return Promise.resolve({ data: {} }); });
// @ts-ignore
FsRequest.delete.mockImplementation(deleteMocked);
return [4 /*yield*/, remove(Object.assign({}, mockedSession, {
signature: 'fakeS',
policy: 'fakeP',
}), 'fakeHandle')];
case 1:
resp = _a.sent();
expect(resp).toEqual({ data: {} });
expect(deleteMocked).toHaveBeenCalledWith('fakeApiUrl/fakeHandle', { params: { key: 'fakeApikey', policy: 'fakeP', signature: 'fakeS' }, filestackHeaders: false });
return [2 /*return*/];
}
});
}); });
it('should respect skip storage option', function () { return __awaiter(void 0, void 0, void 0, function () {
var methodMocked, resp;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
methodMocked = jest.fn(function () { return Promise.resolve({ data: {} }); });
// @ts-ignore
FsRequest.delete.mockImplementation(methodMocked);
return [4 /*yield*/, remove(Object.assign({}, mockedSession, {
signature: 'fakeS',
policy: 'fakeP',
}), 'fakeHandle', true)];
case 1:
resp = _a.sent();
expect(resp).toEqual({ data: {} });
expect(methodMocked).toHaveBeenCalledWith('fakeApiUrl/fakeHandle', { params: { key: 'fakeApikey', policy: 'fakeP', signature: 'fakeS', skip_storage: true }, filestackHeaders: false });
return [2 /*return*/];
}
});
}); });
it('should throw on empty handle', function () {
expect(function () { return remove(mockedSession); }).toThrowError();
});
it('should call remove with provided session', function () { return __awaiter(void 0, void 0, void 0, function () {
var fakeSecurity, resp;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
fakeSecurity = {
signature: 'fakeS',
policy: 'fakeP',
};
// @ts-ignore
FsRequest.delete.mockImplementation(function () { return Promise.resolve({ data: {} }); });
return [4 /*yield*/, remove(mockedSession, 'fakeHandle', false, fakeSecurity)];
case 1:
resp = _a.sent();
expect(resp).toEqual({ data: {} });
return [2 /*return*/];
}
});
}); });
it('should throw on empty signature', function () { return __awaiter(void 0, void 0, void 0, function () {
var fakeSecurity;
return __generator(this, function (_a) {
fakeSecurity = {
signature: null,
policy: 'fakeP',
};
expect(function () { return remove(mockedSession, 'fakeHandle', false, fakeSecurity); }).toThrowError();
return [2 /*return*/];
});
}); });
it('should throw on empty policy', function () { return __awaiter(void 0, void 0, void 0, function () {
var fakeSecurity;
return __generator(this, function (_a) {
fakeSecurity = {
signature: 'fakeS',
policy: null,
};
expect(function () { return remove(mockedSession, 'fakeHandle', false, fakeSecurity); }).toThrowError();
return [2 /*return*/];
});
}); });
it('should throw on empty policy on session', function () { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, expect(function () { return remove(mockedSession, 'fakeHandle'); }).toThrowError()];
});
}); });
});
describe('Retrieve', function () {
it('should make correct retrieve request (GET)', function () { return __awaiter(void 0, void 0, void 0, function () {
var methodMocked, resp;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
methodMocked = jest.fn(function () { return Promise.resolve({ data: {} }); });
// @ts-ignore
FsRequest.dispatch.mockImplementation(methodMocked);
return [4 /*yield*/, retrieve(mockedSession, 'fakeHandle')];
case 1:
resp = _a.sent();
expect(resp).toEqual({});
expect(methodMocked).toHaveBeenCalledWith('fakeApiUrl/fakeHandle', { method: 'GET', params: { key: 'fakeApikey' }, filestackHeaders: false });
return [2 /*return*/];
}
});
}); });
it('should make correct retrieve request (HEAD)', function () { return __awaiter(void 0, void 0, void 0, function () {
var methodMocked, resp;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
methodMocked = jest.fn(function () { return Promise.resolve({ data: {}, headers: { type: 'test' } }); });
// @ts-ignore
FsRequest.dispatch.mockImplementation(methodMocked);
return [4 /*yield*/, retrieve(mockedSession, 'fakeHandle', {
head: true,
})];
case 1:
resp = _a.sent();
expect(resp).toEqual({ type: 'test' });
expect(methodMocked).toHaveBeenCalledWith('fakeApiUrl/fakeHandle', { method: 'HEAD', params: { key: 'fakeApikey' }, filestackHeaders: false });
return [2 /*return*/];
}
});
}); });
it('should make correct retrieve request with provided security', function () { return __awaiter(void 0, void 0, void 0, function () {
var methodMocked, fakeSecurity, resp;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
methodMocked = jest.fn(function () { return Promise.resolve({ data: {} }); });
fakeSecurity = {
signature: 'fakeS',
policy: 'fakeP',
};
// @ts-ignore
FsRequest.dispatch.mockImplementation(methodMocked);
return [4 /*yield*/, retrieve(mockedSession, 'fakeHandle', {}, fakeSecurity)];
case 1:
resp = _a.sent();
expect(resp).toEqual({});
expect(methodMocked).toHaveBeenCalledWith('fakeApiUrl/fakeHandle', {
method: 'GET',
params: { key: 'fakeApikey', policy: 'fakeP', signature: 'fakeS' },
filestackHeaders: false,
});
return [2 /*return*/];
}
});
}); });
it('should make correct retrieve request with extension', function () { return __awaiter(void 0, void 0, void 0, function () {
var methodMocked, resp;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
methodMocked = jest.fn(function () { return Promise.resolve({ data: {} }); });
// @ts-ignore
FsRequest.dispatch.mockImplementation(methodMocked);
return [4 /*yield*/, retrieve(mockedSession, 'fakeHandle', {
extension: 'txt',
})];
case 1:
resp = _a.sent();
expect(resp).toEqual({});
expect(methodMocked).toHaveBeenCalledWith('fakeApiUrl/fakeHandle+txt', { method: 'GET', params: { key: 'fakeApikey' }, filestackHeaders: false });
return [2 /*return*/];
}
});
}); });
it('should make correct retrieve request with metadata', function () { return __awaiter(void 0, void 0, void 0, function () {
var methodMocked, resp;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
methodMocked = jest.fn(function () { return Promise.resolve({ data: {} }); });
// @ts-ignore
FsRequest.dispatch.mockImplementation(methodMocked);
return [4 /*yield*/, retrieve(mockedSession, 'fakeHandle', {
metadata: true,
})];
case 1:
resp = _a.sent();
expect(resp).toEqual({});
expect(methodMocked).toHaveBeenCalledWith('fakeApiUrl/fakeHandle/metadata', { method: 'GET', params: { key: 'fakeApikey' }, filestackHeaders: false });
return [2 /*return*/];
}
});
}); });
it('should throw an error on empty handle', function () {
return expect(function () { return retrieve(mockedSession, ''); }).toThrowError();
});
it('should throw an error worng options provided', function () {
return expect(function () {
return retrieve(mockedSession, 'fakeHandle', {
// @ts-ignore
test: 123,
});
}).toThrowError('Invalid retrieve params');
});
it('should not throw an error worng options provided', function () {
return expect(function () {
return retrieve(mockedSession, 'fakeHandle', {
metadata: true,
});
}).not.toThrowError('Invalid retrieve params');
});
it('should throw an error when metadata and head is provided', function () {
return expect(function () {
return retrieve(mockedSession, 'fakeHandle', {
metadata: true,
head: true,
});
}).toThrowError();
});
});
});
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvYXBpL2ZpbGUuc3BlYy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFDSDs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7O0FBRUgsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUM5RCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBRXpDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUV4QyxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO0FBQzFCLDhCQUE4QjtBQUU5QixJQUFNLGFBQWEsR0FBWTtJQUM3QixNQUFNLEVBQUUsWUFBWTtJQUNwQixJQUFJLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLElBQUksRUFBRTtRQUNuQyxNQUFNLEVBQUUsU0FBUztRQUNqQixVQUFVLEVBQUUsWUFBWTtRQUN4QixZQUFZLEVBQUUsa0JBQWtCO1FBQ2hDLFdBQVcsRUFBRSxpQkFBaUI7UUFDOUIsU0FBUyxFQUFFLGVBQWU7S0FDM0IsQ0FBQztDQUNILENBQUM7QUFFRixRQUFRLENBQUMsU0FBUyxFQUFFO0lBQ2xCLFFBQVEsQ0FBQyxVQUFVLEVBQUU7UUFDbkIsRUFBRSxDQUFDLDhDQUE4QyxFQUFFOzs7Ozt3QkFDM0MsWUFBWSxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsY0FBTSxPQUFBLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBN0IsQ0FBNkIsQ0FBQyxDQUFDO3dCQUNsRSxhQUFhO3dCQUNiLFNBQVMsQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQUMsWUFBWSxDQUFDLENBQUM7d0JBQ2xDLHFCQUFNLFFBQVEsQ0FBQyxhQUFhLEVBQUUsWUFBWSxDQUFDLEVBQUE7O3dCQUFsRCxJQUFJLEdBQUcsU0FBMkM7d0JBRXhELE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQzt3QkFDL0MsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLHdCQUF3QixDQUFDLGdDQUFnQyxFQUFFLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRSxnQkFBZ0IsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDOzs7O2FBQzFILENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQywyQ0FBMkMsRUFBRTs7Ozs7d0JBQ3hDLFlBQVksR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLGNBQU0sT0FBQSxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQTdCLENBQTZCLENBQUMsQ0FBQzt3QkFDbEUsYUFBYTt3QkFDYixTQUFTLENBQUMsR0FBRyxDQUFDLGtCQUFrQixDQUFDLFlBQVksQ0FBQyxDQUFDO3dCQUNsQyxxQkFBTSxRQUFRLENBQUMsYUFBYSxFQUFFLFlBQVksRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FBQyxFQUFBOzt3QkFBbEUsSUFBSSxHQUFHLFNBQTJEO3dCQUV4RSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUM7d0JBQy9DLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQyx3QkFBd0IsQ0FBQyxnQ0FBZ0MsRUFBRSxFQUFFLE1BQU0sRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsRUFBRSxnQkFBZ0IsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDOzs7O2FBQ3RJLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyw4QkFBOEIsRUFBRTs7Z0JBQ2pDLGFBQWE7Z0JBQ2Isc0JBQU8sTUFBTSxDQUFDLGNBQU0sT0FBQSxRQUFRLENBQUMsYUFBYSxFQUFFLFNBQVMsRUFBRSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFoRCxDQUFnRCxDQUFDLENBQUMsWUFBWSxDQUFDLHlCQUF5QixDQUFDLEVBQUM7O2FBQy9HLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyx1Q0FBdUMsRUFBRTtZQUMxQyxPQUFPLE1BQU0sQ0FBQyxjQUFNLE9BQUEsUUFBUSxDQUFDLGFBQWEsQ0FBQyxFQUF2QixDQUF1QixDQUFDLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDOUQsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsMENBQTBDLEVBQUU7Ozs7O3dCQUN2QyxZQUFZLEdBQUc7NEJBQ25CLFNBQVMsRUFBRSxPQUFPOzRCQUNsQixNQUFNLEVBQUUsT0FBTzt5QkFDaEIsQ0FBQzt3QkFFRixhQUFhO3dCQUNiLFNBQVMsQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQUMsY0FBTSxPQUFBLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBN0IsQ0FBNkIsQ0FBQyxDQUFDO3dCQUN6RCxxQkFBTSxRQUFRLENBQUMsYUFBYSxFQUFFLFlBQVksRUFBRSxFQUFFLEVBQUUsWUFBWSxDQUFDLEVBQUE7O3dCQUFwRSxJQUFJLEdBQUcsU0FBNkQ7d0JBRTFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQzs7OzthQUNoRCxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxVQUFVLEVBQUU7UUFDbkIsRUFBRSxDQUFDLDBDQUEwQyxFQUFFOzs7Ozt3QkFDdkMsUUFBUSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7d0JBQzlCLFlBQVksR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLGNBQU0sT0FBQSxPQUFPLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxFQUF6QixDQUF5QixDQUFDLENBQUM7d0JBRTlELGFBQWE7d0JBQ2IsU0FBUyxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxZQUFZLENBQUMsQ0FBQzt3QkFDdkMscUJBQU0sUUFBUSxDQUFDLGFBQWEsRUFBRSxzQkFBc0IsQ0FBQyxFQUFBOzt3QkFBNUQsSUFBSSxHQUFHLFNBQXFEO3dCQUVsRSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDOzs7O2FBQ2hDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLFFBQVEsRUFBRTtRQUNqQixFQUFFLENBQUMsb0JBQW9CLEVBQUU7Ozs7O3dCQUNqQixZQUFZLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxjQUFNLE9BQUEsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUE3QixDQUE2QixDQUFDLENBQUM7d0JBRWxFLGFBQWE7d0JBQ2IsU0FBUyxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxZQUFZLENBQUMsQ0FBQzt3QkFDckMscUJBQU0sTUFBTSxDQUN2QixNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxhQUFhLEVBQUU7Z0NBQy9CLFNBQVMsRUFBRSxPQUFPO2dDQUNsQixNQUFNLEVBQUUsT0FBTzs2QkFDaEIsQ0FBQyxFQUNGLFlBQVksQ0FDYixFQUFBOzt3QkFOSyxJQUFJLEdBQUcsU0FNWjt3QkFFRCxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7d0JBQ25DLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQyxvQkFBb0IsQ0FBQyx1QkFBdUIsRUFBRSxFQUFFLE1BQU0sRUFBRSxFQUFFLEdBQUcsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLEVBQUUsZ0JBQWdCLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQzs7OzthQUNySyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsb0NBQW9DLEVBQUU7Ozs7O3dCQUNqQyxZQUFZLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxjQUFNLE9BQUEsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUE3QixDQUE2QixDQUFDLENBQUM7d0JBRWxFLGFBQWE7d0JBQ2IsU0FBUyxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxZQUFZLENBQUMsQ0FBQzt3QkFDckMscUJBQU0sTUFBTSxDQUN2QixNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxhQUFhLEVBQUU7Z0NBQy9CLFNBQVMsRUFBRSxPQUFPO2dDQUNsQixNQUFNLEVBQUUsT0FBTzs2QkFDaEIsQ0FBQyxFQUNGLFlBQVksRUFDWixJQUFJLENBQ0wsRUFBQTs7d0JBUEssSUFBSSxHQUFHLFNBT1o7d0JBRUQsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO3dCQUNuQyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUMsb0JBQW9CLENBQUMsdUJBQXVCLEVBQUUsRUFBRSxNQUFNLEVBQUUsRUFBRSxHQUFHLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLEVBQUUsZ0JBQWdCLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQzs7OzthQUN6TCxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsOEJBQThCLEVBQUU7WUFDakMsTUFBTSxDQUFDLGNBQU0sT0FBQSxNQUFNLENBQUMsYUFBYSxDQUFDLEVBQXJCLENBQXFCLENBQUMsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNyRCxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQywwQ0FBMEMsRUFBRTs7Ozs7d0JBQ3ZDLFlBQVksR0FBRzs0QkFDbkIsU0FBUyxFQUFFLE9BQU87NEJBQ2xCLE1BQU0sRUFBRSxPQUFPO3lCQUNoQixDQUFDO3dCQUVGLGFBQWE7d0JBQ2IsU0FBUyxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxjQUFNLE9BQUEsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUE3QixDQUE2QixDQUFDLENBQUM7d0JBQzVELHFCQUFNLE1BQU0sQ0FBQyxhQUFhLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxZQUFZLENBQUMsRUFBQTs7d0JBQXJFLElBQUksR0FBRyxTQUE4RDt3QkFFM0UsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDOzs7O2FBQ3BDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxpQ0FBaUMsRUFBRTs7O2dCQUM5QixZQUFZLEdBQUc7b0JBQ25CLFNBQVMsRUFBRSxJQUFJO29CQUNmLE1BQU0sRUFBRSxPQUFPO2lCQUNoQixDQUFDO2dCQUVGLE1BQU0sQ0FBQyxjQUFNLE9BQUEsTUFBTSxDQUFDLGFBQWEsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLFlBQVksQ0FBQyxFQUF4RCxDQUF3RCxDQUFDLENBQUMsWUFBWSxFQUFFLENBQUM7OzthQUN2RixDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsOEJBQThCLEVBQUU7OztnQkFDM0IsWUFBWSxHQUFHO29CQUNuQixTQUFTLEVBQUUsT0FBTztvQkFDbEIsTUFBTSxFQUFFLElBQUk7aUJBQ2IsQ0FBQztnQkFFRixNQUFNLENBQUMsY0FBTSxPQUFBLE1BQU0sQ0FBQyxhQUFhLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxZQUFZLENBQUMsRUFBeEQsQ0FBd0QsQ0FBQyxDQUFDLFlBQVksRUFBRSxDQUFDOzs7YUFDdkYsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLHlDQUF5QyxFQUFFOztnQkFDNUMsc0JBQU8sTUFBTSxDQUFDLGNBQU0sT0FBQSxNQUFNLENBQUMsYUFBYSxFQUFFLFlBQVksQ0FBQyxFQUFuQyxDQUFtQyxDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUM7O2FBQ3pFLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLFVBQVUsRUFBRTtRQUNuQixFQUFFLENBQUMsNENBQTRDLEVBQUU7Ozs7O3dCQUN6QyxZQUFZLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxjQUFNLE9BQUEsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUE3QixDQUE2QixDQUFDLENBQUM7d0JBRWxFLGFBQWE7d0JBQ2IsU0FBUyxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxZQUFZLENBQUMsQ0FBQzt3QkFDdkMscUJBQU0sUUFBUSxDQUFDLGFBQWEsRUFBRSxZQUFZLENBQUMsRUFBQTs7d0JBQWxELElBQUksR0FBRyxTQUEyQzt3QkFFeEQsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQzt3QkFDekIsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLG9CQUFvQixDQUFDLHVCQUF1QixFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsRUFBRSxHQUFHLEVBQUUsWUFBWSxFQUFFLEVBQUUsZ0JBQWdCLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQzs7OzthQUMvSSxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsNkNBQTZDLEVBQUU7Ozs7O3dCQUMxQyxZQUFZLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxjQUFNLE9BQUEsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxFQUFFLENBQUMsRUFBeEQsQ0FBd0QsQ0FBQyxDQUFDO3dCQUU3RixhQUFhO3dCQUNiLFNBQVMsQ0FBQyxRQUFRLENBQUMsa0JBQWtCLENBQUMsWUFBWSxDQUFDLENBQUM7d0JBQ3ZDLHFCQUFNLFFBQVEsQ0FBQyxhQUFhLEVBQUUsWUFBWSxFQUFFO2dDQUN2RCxJQUFJLEVBQUUsSUFBSTs2QkFDWCxDQUFDLEVBQUE7O3dCQUZJLElBQUksR0FBRyxTQUVYO3dCQUVGLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQzt3QkFDdkMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLG9CQUFvQixDQUFDLHVCQUF1QixFQUFFLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsRUFBRSxHQUFHLEVBQUUsWUFBWSxFQUFFLEVBQUUsZ0JBQWdCLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQzs7OzthQUNoSixDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsNkRBQTZELEVBQUU7Ozs7O3dCQUMxRCxZQUFZLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxjQUFNLE9BQUEsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUE3QixDQUE2QixDQUFDLENBQUM7d0JBRTVELFlBQVksR0FBRzs0QkFDbkIsU0FBUyxFQUFFLE9BQU87NEJBQ2xCLE1BQU0sRUFBRSxPQUFPO3lCQUNoQixDQUFDO3dCQUVGLGFBQWE7d0JBQ2IsU0FBUyxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxZQUFZLENBQUMsQ0FBQzt3QkFDdkMscUJBQU0sUUFBUSxDQUFDLGFBQWEsRUFBRSxZQUFZLEVBQUUsRUFBRSxFQUFFLFlBQVksQ0FBQyxFQUFBOzt3QkFBcEUsSUFBSSxHQUFHLFNBQTZEO3dCQUUxRSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDO3dCQUN6QixNQUFNLENBQUMsWUFBWSxDQUFDLENBQUMsb0JBQW9CLENBQUMsdUJBQXVCLEVBQUU7NEJBQ2pFLE1BQU0sRUFBRSxLQUFLOzRCQUNiLE1BQU0sRUFBRSxFQUFFLEdBQUcsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFOzRCQUNsRSxnQkFBZ0IsRUFBRSxLQUFLO3lCQUN4QixDQUFDLENBQUM7Ozs7YUFDSixDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMscURBQXFELEVBQUU7Ozs7O3dCQUNsRCxZQUFZLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxjQUFNLE9BQUEsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUE3QixDQUE2QixDQUFDLENBQUM7d0JBRWxFLGFBQWE7d0JBQ2IsU0FBUyxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxZQUFZLENBQUMsQ0FBQzt3QkFDdkMscUJBQU0sUUFBUSxDQUFDLGFBQWEsRUFBRSxZQUFZLEVBQUU7Z0NBQ3ZELFNBQVMsRUFBRSxLQUFLOzZCQUNqQixDQUFDLEVBQUE7O3dCQUZJLElBQUksR0FBRyxTQUVYO3dCQUVGLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7d0JBQ3pCLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQyxvQkFBb0IsQ0FBQywyQkFBMkIsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEVBQUUsR0FBRyxFQUFFLFlBQVksRUFBRSxFQUFFLGdCQUFnQixFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7Ozs7YUFDbkosQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLG9EQUFvRCxFQUFFOzs7Ozt3QkFDakQsWUFBWSxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsY0FBTSxPQUFBLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBN0IsQ0FBNkIsQ0FBQyxDQUFDO3dCQUVsRSxhQUFhO3dCQUNiLFNBQVMsQ0FBQyxRQUFRLENBQUMsa0JBQWtCLENBQUMsWUFBWSxDQUFDLENBQUM7d0JBQ3ZDLHFCQUFNLFFBQVEsQ0FBQyxhQUFhLEVBQUUsWUFBWSxFQUFFO2dDQUN2RCxRQUFRLEVBQUUsSUFBSTs2QkFDZixDQUFDLEVBQUE7O3dCQUZJLElBQUksR0FBRyxTQUVYO3dCQUVGLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7d0JBQ3pCLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQyxvQkFBb0IsQ0FBQyxnQ0FBZ0MsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEVBQUUsR0FBRyxFQUFFLFlBQVksRUFBRSxFQUFFLGdCQUFnQixFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7Ozs7YUFDeEosQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLHVDQUF1QyxFQUFFO1lBQzFDLE9BQU8sTUFBTSxDQUFDLGNBQU0sT0FBQSxRQUFRLENBQUMsYUFBYSxFQUFFLEVBQUUsQ0FBQyxFQUEzQixDQUEyQixDQUFDLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDbEUsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsOENBQThDLEVBQUU7WUFDakQsT0FBTyxNQUFNLENBQUM7Z0JBQ1osT0FBQSxRQUFRLENBQUMsYUFBYSxFQUFFLFlBQVksRUFBRTtvQkFDcEMsYUFBYTtvQkFDYixJQUFJLEVBQUUsR0FBRztpQkFDVixDQUFDO1lBSEYsQ0FHRSxDQUNILENBQUMsWUFBWSxDQUFDLHlCQUF5QixDQUFDLENBQUM7UUFDNUMsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsa0RBQWtELEVBQUU7WUFDckQsT0FBTyxNQUFNLENBQUM7Z0JBQ1osT0FBQSxRQUFRLENBQUMsYUFBYSxFQUFFLFlBQVksRUFBRTtvQkFDcEMsUUFBUSxFQUFFLElBQUk7aUJBQ2YsQ0FBQztZQUZGLENBRUUsQ0FDSCxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMseUJBQXlCLENBQUMsQ0FBQztRQUNoRCxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQywwREFBMEQsRUFBRTtZQUM3RCxPQUFPLE1BQU0sQ0FBQztnQkFDWixPQUFBLFFBQVEsQ0FBQyxhQUFhLEVBQUUsWUFBWSxFQUFFO29CQUNwQyxRQUFRLEVBQUUsSUFBSTtvQkFDZCxJQUFJLEVBQUUsSUFBSTtpQkFDWCxDQUFDO1lBSEYsQ0FHRSxDQUNILENBQUMsWUFBWSxFQUFFLENBQUM7UUFDbkIsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwiZmlsZSI6ImxpYi9hcGkvZmlsZS5zcGVjLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoYykgMjAxOCBieSBGaWxlc3RhY2suXG4gKiBTb21lIHJpZ2h0cyByZXNlcnZlZC5cbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cbi8qXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTggYnkgRmlsZXN0YWNrLlxuICogU29tZSByaWdodHMgcmVzZXJ2ZWQuXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IHJldHJpZXZlLCByZW1vdmUsIG1ldGFkYXRhLCBkb3dubG9hZCB9IGZyb20gJy4vZmlsZSc7XG5pbXBvcnQgeyBGc1JlcXVlc3QgfSBmcm9tICcuLy4uL3JlcXVlc3QnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uL2NsaWVudCc7XG5pbXBvcnQgeyBjb25maWcgfSBmcm9tICcuLy4uLy4uL2NvbmZpZyc7XG5cbmplc3QubW9jaygnLi8uLi9yZXF1ZXN0Jyk7XG4vLyBqZXN0Lm1vY2soJy4vLi4vZmlsZWxpbmsnKTtcblxuY29uc3QgbW9ja2VkU2Vzc2lvbjogU2Vzc2lvbiA9IHtcbiAgYXBpa2V5OiAnZmFrZUFwaWtleScsXG4gIHVybHM6IE9iamVjdC5hc3NpZ24oe30sIGNvbmZpZy51cmxzLCB7XG4gICAgY2RuVXJsOiAnZmFrZVVybCcsXG4gICAgZmlsZUFwaVVybDogJ2Zha2VBcGlVcmwnLFxuICAgIHVwbG9hZEFwaVVybDogJ2Zha2VVcGxvYWRBcGlVcmwnLFxuICAgIGNsb3VkQXBpVXJsOiAnZmFrZUNsb3VkQXBpVXJsJyxcbiAgICBwaWNrZXJVcmw6ICdmYWtlUGlja2VyVXJsJyxcbiAgfSksXG59O1xuXG5kZXNjcmliZSgnRmlsZUFQSScsICgpID0+IHtcbiAgZGVzY3JpYmUoJ01ldGFkYXRhJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgY2FsbCBjb3JyZWN0IG1ldGFkYXRhIHdpdGhvdXQgb3B0aW9ucycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IG1ldGhvZE1vY2tlZCA9IGplc3QuZm4oKCkgPT4gUHJvbWlzZS5yZXNvbHZlKHsgZGF0YToge30gfSkpO1xuICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgRnNSZXF1ZXN0LmdldC5tb2NrSW1wbGVtZW50YXRpb24obWV0aG9kTW9ja2VkKTtcbiAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCBtZXRhZGF0YShtb2NrZWRTZXNzaW9uLCAnZmFrZUhhbmRsZScpO1xuXG4gICAgICBleHBlY3QocmVzcCkudG9FcXVhbCh7IGhhbmRsZTogJ2Zha2VIYW5kbGUnIH0pO1xuICAgICAgZXhwZWN0KG1ldGhvZE1vY2tlZCkudG9IYXZlQmVlbkxhc3RDYWxsZWRXaXRoKCdmYWtlQXBpVXJsL2Zha2VIYW5kbGUvbWV0YWRhdGEnLCB7IHBhcmFtczoge30sIGZpbGVzdGFja0hlYWRlcnM6IGZhbHNlIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBjYWxsIGNvcnJlY3QgbWV0YWRhdGEgd2l0aCBvcHRpb25zJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgbWV0aG9kTW9ja2VkID0gamVzdC5mbigoKSA9PiBQcm9taXNlLnJlc29sdmUoeyBkYXRhOiB7fSB9KSk7XG4gICAgICAvLyBAdHMtaWdub3JlXG4gICAgICBGc1JlcXVlc3QuZ2V0Lm1vY2tJbXBsZW1lbnRhdGlvbihtZXRob2RNb2NrZWQpO1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IG1ldGFkYXRhKG1vY2tlZFNlc3Npb24sICdmYWtlSGFuZGxlJywgeyBzaXplOiB0cnVlIH0pO1xuXG4gICAgICBleHBlY3QocmVzcCkudG9FcXVhbCh7IGhhbmRsZTogJ2Zha2VIYW5kbGUnIH0pO1xuICAgICAgZXhwZWN0KG1ldGhvZE1vY2tlZCkudG9IYXZlQmVlbkxhc3RDYWxsZWRXaXRoKCdmYWtlQXBpVXJsL2Zha2VIYW5kbGUvbWV0YWRhdGEnLCB7IHBhcmFtczogeyBzaXplOiB0cnVlIH0sIGZpbGVzdGFja0hlYWRlcnM6IGZhbHNlIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBvbiB3cm9uZyBvcHRpb24nLCBhc3luYyAoKSA9PiB7XG4gICAgICAvLyBAdHMtaWdub3JlXG4gICAgICByZXR1cm4gZXhwZWN0KCgpID0+IG1ldGFkYXRhKG1vY2tlZFNlc3Npb24sICdmYWtla2V5JywgeyBibGE6IDEyMyB9KSkudG9UaHJvd0Vycm9yKCdJbnZhbGlkIG1ldGFkYXRhIHBhcmFtcycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBhbiBlcnJvciBvbiBlbXB0eSBoYW5kbGUnLCAoKSA9PiB7XG4gICAgICByZXR1cm4gZXhwZWN0KCgpID0+IG1ldGFkYXRhKG1vY2tlZFNlc3Npb24pKS50b1Rocm93RXJyb3IoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVzcGVjdCBwcm92aWRlZCBzZWN1cml0eSBvcHRpb25zJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgZmFrZVNlY3VyaXR5ID0ge1xuICAgICAgICBzaWduYXR1cmU6ICdmYWtlUycsXG4gICAgICAgIHBvbGljeTogJ2Zha2VQJyxcbiAgICAgIH07XG5cbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIEZzUmVxdWVzdC5nZXQubW9ja0ltcGxlbWVudGF0aW9uKCgpID0+IFByb21pc2UucmVzb2x2ZSh7IGRhdGE6IHt9IH0pKTtcbiAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCBtZXRhZGF0YShtb2NrZWRTZXNzaW9uLCAnZmFrZUhhbmRsZScsIHt9LCBmYWtlU2VjdXJpdHkpO1xuXG4gICAgICBleHBlY3QocmVzcCkudG9FcXVhbCh7IGhhbmRsZTogJ2Zha2VIYW5kbGUnIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnRG93bmxvYWQnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gYnVmZmVyIG9uIGRvd25sb2FkIHJlcXVlc3QnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0ZXN0UmVzcCA9IEJ1ZmZlci5mcm9tKCcxMjMnKTtcbiAgICAgIGNvbnN0IG1ldGhvZE1vY2tlZCA9IGplc3QuZm4oKCkgPT4gUHJvbWlzZS5yZXNvbHZlKHRlc3RSZXNwKSk7XG5cbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIEZzUmVxdWVzdC5kaXNwYXRjaC5tb2NrSW1wbGVtZW50YXRpb24obWV0aG9kTW9ja2VkKTtcbiAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCBkb3dubG9hZChtb2NrZWRTZXNzaW9uLCAnZ05ETkNEV05US3FvR0ZJU2RkMkEnKTtcblxuICAgICAgZXhwZWN0KHJlc3ApLnRvRXF1YWwodGVzdFJlc3ApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnUmVtb3ZlJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgY2FsbCByZW1vdmUnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBkZWxldGVNb2NrZWQgPSBqZXN0LmZuKCgpID0+IFByb21pc2UucmVzb2x2ZSh7IGRhdGE6IHt9IH0pKTtcblxuICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgRnNSZXF1ZXN0LmRlbGV0ZS5tb2NrSW1wbGVtZW50YXRpb24oZGVsZXRlTW9ja2VkKTtcbiAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCByZW1vdmUoXG4gICAgICAgIE9iamVjdC5hc3NpZ24oe30sIG1vY2tlZFNlc3Npb24sIHtcbiAgICAgICAgICBzaWduYXR1cmU6ICdmYWtlUycsXG4gICAgICAgICAgcG9saWN5OiAnZmFrZVAnLFxuICAgICAgICB9KSxcbiAgICAgICAgJ2Zha2VIYW5kbGUnXG4gICAgICApO1xuXG4gICAgICBleHBlY3QocmVzcCkudG9FcXVhbCh7IGRhdGE6IHt9IH0pO1xuICAgICAgZXhwZWN0KGRlbGV0ZU1vY2tlZCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoJ2Zha2VBcGlVcmwvZmFrZUhhbmRsZScsIHsgcGFyYW1zOiB7IGtleTogJ2Zha2VBcGlrZXknLCBwb2xpY3k6ICdmYWtlUCcsIHNpZ25hdHVyZTogJ2Zha2VTJyB9LCBmaWxlc3RhY2tIZWFkZXJzOiBmYWxzZSB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVzcGVjdCBza2lwIHN0b3JhZ2Ugb3B0aW9uJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgbWV0aG9kTW9ja2VkID0gamVzdC5mbigoKSA9PiBQcm9taXNlLnJlc29sdmUoeyBkYXRhOiB7fSB9KSk7XG5cbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIEZzUmVxdWVzdC5kZWxldGUubW9ja0ltcGxlbWVudGF0aW9uKG1ldGhvZE1vY2tlZCk7XG4gICAgICBjb25zdCByZXNwID0gYXdhaXQgcmVtb3ZlKFxuICAgICAgICBPYmplY3QuYXNzaWduKHt9LCBtb2NrZWRTZXNzaW9uLCB7XG4gICAgICAgICAgc2lnbmF0dXJlOiAnZmFrZVMnLFxuICAgICAgICAgIHBvbGljeTogJ2Zha2VQJyxcbiAgICAgICAgfSksXG4gICAgICAgICdmYWtlSGFuZGxlJyxcbiAgICAgICAgdHJ1ZVxuICAgICAgKTtcblxuICAgICAgZXhwZWN0KHJlc3ApLnRvRXF1YWwoeyBkYXRhOiB7fSB9KTtcbiAgICAgIGV4cGVjdChtZXRob2RNb2NrZWQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKCdmYWtlQXBpVXJsL2Zha2VIYW5kbGUnLCB7IHBhcmFtczogeyBrZXk6ICdmYWtlQXBpa2V5JywgcG9saWN5OiAnZmFrZVAnLCBzaWduYXR1cmU6ICdmYWtlUycsIHNraXBfc3RvcmFnZTogdHJ1ZSB9LCBmaWxlc3RhY2tIZWFkZXJzOiBmYWxzZSB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgb24gZW1wdHkgaGFuZGxlJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KCgpID0+IHJlbW92ZShtb2NrZWRTZXNzaW9uKSkudG9UaHJvd0Vycm9yKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNhbGwgcmVtb3ZlIHdpdGggcHJvdmlkZWQgc2Vzc2lvbicsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGZha2VTZWN1cml0eSA9IHtcbiAgICAgICAgc2lnbmF0dXJlOiAnZmFrZVMnLFxuICAgICAgICBwb2xpY3k6ICdmYWtlUCcsXG4gICAgICB9O1xuXG4gICAgICAvLyBAdHMtaWdub3JlXG4gICAgICBGc1JlcXVlc3QuZGVsZXRlLm1vY2tJbXBsZW1lbnRhdGlvbigoKSA9PiBQcm9taXNlLnJlc29sdmUoeyBkYXRhOiB7fSB9KSk7XG4gICAgICBjb25zdCByZXNwID0gYXdhaXQgcmVtb3ZlKG1vY2tlZFNlc3Npb24sICdmYWtlSGFuZGxlJywgZmFsc2UsIGZha2VTZWN1cml0eSk7XG5cbiAgICAgIGV4cGVjdChyZXNwKS50b0VxdWFsKHsgZGF0YToge30gfSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IG9uIGVtcHR5IHNpZ25hdHVyZScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGZha2VTZWN1cml0eSA9IHtcbiAgICAgICAgc2lnbmF0dXJlOiBudWxsLFxuICAgICAgICBwb2xpY3k6ICdmYWtlUCcsXG4gICAgICB9O1xuXG4gICAgICBleHBlY3QoKCkgPT4gcmVtb3ZlKG1vY2tlZFNlc3Npb24sICdmYWtlSGFuZGxlJywgZmFsc2UsIGZha2VTZWN1cml0eSkpLnRvVGhyb3dFcnJvcigpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBvbiBlbXB0eSBwb2xpY3knLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBmYWtlU2VjdXJpdHkgPSB7XG4gICAgICAgIHNpZ25hdHVyZTogJ2Zha2VTJyxcbiAgICAgICAgcG9saWN5OiBudWxsLFxuICAgICAgfTtcblxuICAgICAgZXhwZWN0KCgpID0+IHJlbW92ZShtb2NrZWRTZXNzaW9uLCAnZmFrZUhhbmRsZScsIGZhbHNlLCBmYWtlU2VjdXJpdHkpKS50b1Rocm93RXJyb3IoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgb24gZW1wdHkgcG9saWN5IG9uIHNlc3Npb24nLCBhc3luYyAoKSA9PiB7XG4gICAgICByZXR1cm4gZXhwZWN0KCgpID0+IHJlbW92ZShtb2NrZWRTZXNzaW9uLCAnZmFrZUhhbmRsZScpKS50b1Rocm93RXJyb3IoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1JldHJpZXZlJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgbWFrZSBjb3JyZWN0IHJldHJpZXZlIHJlcXVlc3QgKEdFVCknLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBtZXRob2RNb2NrZWQgPSBqZXN0LmZuKCgpID0+IFByb21pc2UucmVzb2x2ZSh7IGRhdGE6IHt9IH0pKTtcblxuICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgRnNSZXF1ZXN0LmRpc3BhdGNoLm1vY2tJbXBsZW1lbnRhdGlvbihtZXRob2RNb2NrZWQpO1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHJldHJpZXZlKG1vY2tlZFNlc3Npb24sICdmYWtlSGFuZGxlJyk7XG5cbiAgICAgIGV4cGVjdChyZXNwKS50b0VxdWFsKHt9KTtcbiAgICAgIGV4cGVjdChtZXRob2RNb2NrZWQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKCdmYWtlQXBpVXJsL2Zha2VIYW5kbGUnLCB7IG1ldGhvZDogJ0dFVCcsIHBhcmFtczogeyBrZXk6ICdmYWtlQXBpa2V5JyB9LCBmaWxlc3RhY2tIZWFkZXJzOiBmYWxzZSB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgbWFrZSBjb3JyZWN0IHJldHJpZXZlIHJlcXVlc3QgKEhFQUQpJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgbWV0aG9kTW9ja2VkID0gamVzdC5mbigoKSA9PiBQcm9taXNlLnJlc29sdmUoeyBkYXRhOiB7fSwgaGVhZGVyczogeyB0eXBlOiAndGVzdCcgfSB9KSk7XG5cbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIEZzUmVxdWVzdC5kaXNwYXRjaC5tb2NrSW1wbGVtZW50YXRpb24obWV0aG9kTW9ja2VkKTtcbiAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCByZXRyaWV2ZShtb2NrZWRTZXNzaW9uLCAnZmFrZUhhbmRsZScsIHtcbiAgICAgICAgaGVhZDogdHJ1ZSxcbiAgICAgIH0pO1xuXG4gICAgICBleHBlY3QocmVzcCkudG9FcXVhbCh7IHR5cGU6ICd0ZXN0JyB9KTtcbiAgICAgIGV4cGVjdChtZXRob2RNb2NrZWQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKCdmYWtlQXBpVXJsL2Zha2VIYW5kbGUnLCB7IG1ldGhvZDogJ0hFQUQnLCBwYXJhbXM6IHsga2V5OiAnZmFrZUFwaWtleScgfSwgZmlsZXN0YWNrSGVhZGVyczogZmFsc2UgfSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIG1ha2UgY29ycmVjdCByZXRyaWV2ZSByZXF1ZXN0IHdpdGggcHJvdmlkZWQgc2VjdXJpdHknLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBtZXRob2RNb2NrZWQgPSBqZXN0LmZuKCgpID0+IFByb21pc2UucmVzb2x2ZSh7IGRhdGE6IHt9IH0pKTtcblxuICAgICAgY29uc3QgZmFrZVNlY3VyaXR5ID0ge1xuICAgICAgICBzaWduYXR1cmU6ICdmYWtlUycsXG4gICAgICAgIHBvbGljeTogJ2Zha2VQJyxcbiAgICAgIH07XG5cbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIEZzUmVxdWVzdC5kaXNwYXRjaC5tb2NrSW1wbGVtZW50YXRpb24obWV0aG9kTW9ja2VkKTtcbiAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCByZXRyaWV2ZShtb2NrZWRTZXNzaW9uLCAnZmFrZUhhbmRsZScsIHt9LCBmYWtlU2VjdXJpdHkpO1xuXG4gICAgICBleHBlY3QocmVzcCkudG9FcXVhbCh7fSk7XG4gICAgICBleHBlY3QobWV0aG9kTW9ja2VkKS50b0hhdmVCZWVuQ2FsbGVkV2l0aCgnZmFrZUFwaVVybC9mYWtlSGFuZGxlJywge1xuICAgICAgICBtZXRob2Q6ICdHRVQnLFxuICAgICAgICBwYXJhbXM6IHsga2V5OiAnZmFrZUFwaWtleScsIHBvbGljeTogJ2Zha2VQJywgc2lnbmF0dXJlOiAnZmFrZVMnIH0sXG4gICAgICAgIGZpbGVzdGFja0hlYWRlcnM6IGZhbHNlLFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIG1ha2UgY29ycmVjdCByZXRyaWV2ZSByZXF1ZXN0IHdpdGggZXh0ZW5zaW9uJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgbWV0aG9kTW9ja2VkID0gamVzdC5mbigoKSA9PiBQcm9taXNlLnJlc29sdmUoeyBkYXRhOiB7fSB9KSk7XG5cbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIEZzUmVxdWVzdC5kaXNwYXRjaC5tb2NrSW1wbGVtZW50YXRpb24obWV0aG9kTW9ja2VkKTtcbiAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCByZXRyaWV2ZShtb2NrZWRTZXNzaW9uLCAnZmFrZUhhbmRsZScsIHtcbiAgICAgICAgZXh0ZW5zaW9uOiAndHh0JyxcbiAgICAgIH0pO1xuXG4gICAgICBleHBlY3QocmVzcCkudG9FcXVhbCh7fSk7XG4gICAgICBleHBlY3QobWV0aG9kTW9ja2VkKS50b0hhdmVCZWVuQ2FsbGVkV2l0aCgnZmFrZUFwaVVybC9mYWtlSGFuZGxlK3R4dCcsIHsgbWV0aG9kOiAnR0VUJywgcGFyYW1zOiB7IGtleTogJ2Zha2VBcGlrZXknIH0sIGZpbGVzdGFja0hlYWRlcnM6IGZhbHNlIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBtYWtlIGNvcnJlY3QgcmV0cmlldmUgcmVxdWVzdCB3aXRoIG1ldGFkYXRhJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgbWV0aG9kTW9ja2VkID0gamVzdC5mbigoKSA9PiBQcm9taXNlLnJlc29sdmUoeyBkYXRhOiB7fSB9KSk7XG5cbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIEZzUmVxdWVzdC5kaXNwYXRjaC5tb2NrSW1wbGVtZW50YXRpb24obWV0aG9kTW9ja2VkKTtcbiAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCByZXRyaWV2ZShtb2NrZWRTZXNzaW9uLCAnZmFrZUhhbmRsZScsIHtcbiAgICAgICAgbWV0YWRhdGE6IHRydWUsXG4gICAgICB9KTtcblxuICAgICAgZXhwZWN0KHJlc3ApLnRvRXF1YWwoe30pO1xuICAgICAgZXhwZWN0KG1ldGhvZE1vY2tlZCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoJ2Zha2VBcGlVcmwvZmFrZUhhbmRsZS9tZXRhZGF0YScsIHsgbWV0aG9kOiAnR0VUJywgcGFyYW1zOiB7IGtleTogJ2Zha2VBcGlrZXknIH0sIGZpbGVzdGFja0hlYWRlcnM6IGZhbHNlIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBhbiBlcnJvciBvbiBlbXB0eSBoYW5kbGUnLCAoKSA9PiB7XG4gICAgICByZXR1cm4gZXhwZWN0KCgpID0+IHJldHJpZXZlKG1vY2tlZFNlc3Npb24sICcnKSkudG9UaHJvd0Vycm9yKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGFuIGVycm9yIHdvcm5nIG9wdGlvbnMgcHJvdmlkZWQnLCAoKSA9PiB7XG4gICAgICByZXR1cm4gZXhwZWN0KCgpID0+XG4gICAgICAgIHJldHJpZXZlKG1vY2tlZFNlc3Npb24sICdmYWtlSGFuZGxlJywge1xuICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICB0ZXN0OiAxMjMsXG4gICAgICAgIH0pXG4gICAgICApLnRvVGhyb3dFcnJvcignSW52YWxpZCByZXRyaWV2ZSBwYXJhbXMnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgbm90IHRocm93IGFuIGVycm9yIHdvcm5nIG9wdGlvbnMgcHJvdmlkZWQnLCAoKSA9PiB7XG4gICAgICByZXR1cm4gZXhwZWN0KCgpID0+XG4gICAgICAgIHJldHJpZXZlKG1vY2tlZFNlc3Npb24sICdmYWtlSGFuZGxlJywge1xuICAgICAgICAgIG1ldGFkYXRhOiB0cnVlLFxuICAgICAgICB9KVxuICAgICAgKS5ub3QudG9UaHJvd0Vycm9yKCdJbnZhbGlkIHJldHJpZXZlIHBhcmFtcycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBhbiBlcnJvciB3aGVuIG1ldGFkYXRhIGFuZCBoZWFkIGlzIHByb3ZpZGVkJywgKCkgPT4ge1xuICAgICAgcmV0dXJuIGV4cGVjdCgoKSA9PlxuICAgICAgICByZXRyaWV2ZShtb2NrZWRTZXNzaW9uLCAnZmFrZUhhbmRsZScsIHtcbiAgICAgICAgICBtZXRhZGF0YTogdHJ1ZSxcbiAgICAgICAgICBoZWFkOiB0cnVlLFxuICAgICAgICB9KVxuICAgICAgKS50b1Rocm93RXJyb3IoKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==