UNPKG

filestack-js

Version:

Official JavaScript library for Filestack

354 lines (352 loc) 43.7 kB
/* * 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvYXBpL2ZpbGUuc3BlYy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFDSDs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7O0FBRUgsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUM5RCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBRXpDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUV4QyxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO0FBQzFCLDhCQUE4QjtBQUU5QixJQUFNLGFBQWEsR0FBWTtJQUM3QixNQUFNLEVBQUUsWUFBWTtJQUNwQixJQUFJLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLElBQUksRUFBRTtRQUNuQyxNQUFNLEVBQUUsU0FBUztRQUNqQixVQUFVLEVBQUUsWUFBWTtRQUN4QixZQUFZLEVBQUUsa0JBQWtCO1FBQ2hDLFdBQVcsRUFBRSxpQkFBaUI7UUFDOUIsU0FBUyxFQUFFLGVBQWU7S0FDM0IsQ0FBQztDQUNILENBQUM7QUFFRixRQUFRLENBQUMsU0FBUyxFQUFFO0lBQ2xCLFFBQVEsQ0FBQyxVQUFVLEVBQUU7UUFDbkIsRUFBRSxDQUFDLDhDQUE4QyxFQUFFOzs7Ozt3QkFDM0MsWUFBWSxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsY0FBTSxPQUFBLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBN0IsQ0FBNkIsQ0FBQyxDQUFDO3dCQUNsRSxhQUFhO3dCQUNiLFNBQVMsQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQUMsWUFBWSxDQUFDLENBQUM7d0JBQ2xDLHFCQUFNLFFBQVEsQ0FBQyxhQUFhLEVBQUUsWUFBWSxDQUFDLEVBQUE7O3dCQUFsRCxJ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QUFDO1lBSEYsQ0FHRSxDQUNILENBQUMsWUFBWSxFQUFFLENBQUM7UUFDbkIsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwiZmlsZSI6ImxpYi9hcGkvZmlsZS5zcGVjLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoYykgMjAxOCBieSBGaWxlc3RhY2suXG4gKiBTb21lIHJpZ2h0cyByZXNlcnZlZC5cbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cbi8qXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTggYnkgRmlsZXN0YWNrLlxuICogU29tZSByaWdodHMgcmVzZXJ2ZWQuXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IHJldHJpZXZlLCByZW1vdmUsIG1ldGFkYXRhLCBkb3dubG9hZCB9IGZyb20gJy4vZmlsZSc7XG5pbXBvcnQgeyBGc1JlcXVlc3QgfSBmcm9tICcuLy4uL3JlcXVlc3QnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uL2NsaWVudCc7XG5pbXBvcnQgeyBjb25maWcgfSBmcm9tICcuLy4uLy4uL2NvbmZpZyc7XG5cbmplc3QubW9jaygnLi8uLi9yZXF1ZXN0Jyk7XG4vLyBqZXN0Lm1vY2soJy4vLi4vZmlsZWxpbmsnKTtcblxuY29uc3QgbW9ja2VkU2Vzc2lvbjogU2Vzc2lvbiA9IHtcbiAgYXBpa2V5OiAnZmFrZUFwaWtleScsXG4gIHVybHM6IE9iamVjdC5hc3NpZ24oe30sIGNvbmZpZy51cmxzLCB7XG4gICAgY2RuVXJsOiAnZmFrZVVybCcsXG4gICAgZmlsZUFwaVVybDogJ2Zha2VBcGlVcmwnLFxuICAgIHVwbG9hZEFwaVVybDogJ2Zha2VVcGxvYWRBcGlVcmwnLFxuICAgIGNsb3VkQXBpVXJsOiAnZmFrZUNsb3VkQXBpVXJsJyxcbiAgICBwaWNrZXJVcmw6ICdmYWtlUGlja2VyVXJsJyxcbiAgfSksXG59O1xuXG5kZXNjcmliZSgnRmlsZUFQSScsICgpID0+IHtcbiAgZGVzY3JpYmUoJ01ldGFkYXRhJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgY2FsbCBjb3JyZWN0IG1ldGFkYXRhIHdpdGhvdXQgb3B0aW9ucycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IG1ldGhvZE1vY2tlZCA9IGplc3QuZm4oKCkgPT4gUHJvbWlzZS5yZXNvbHZlKHsgZGF0YToge30gfSkpO1xuICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgRnNSZXF1ZXN0LmdldC5tb2NrSW1wbGVtZW50YXRpb24obWV0aG9kTW9ja2VkKTtcbiAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCBtZXRhZGF0YShtb2NrZWRTZXNzaW9uLCAnZmFrZUhhbmRsZScpO1xuXG4gICAgICBleHBlY3QocmVzcCkudG9FcXVhbCh7IGhhbmRsZTogJ2Zha2VIYW5kbGUnIH0pO1xuICAgICAgZXhwZWN0KG1ldGhvZE1vY2tlZCkudG9IYXZlQmVlbkxhc3RDYWxsZWRXaXRoKCdmYWtlQXBpVXJsL2Zha2VIYW5kbGUvbWV0YWRhdGEnLCB7IHBhcmFtczoge30sIGZpbGVzdGFja0hlYWRlcnM6IGZhbHNlIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBjYWxsIGNvcnJlY3QgbWV0YWRhdGEgd2l0aCBvcHRpb25zJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgbWV0aG9kTW9ja2VkID0gamVzdC5mbigoKSA9PiBQcm9taXNlLnJlc29sdmUoeyBkYXRhOiB7fSB9KSk7XG4gICAgICAvLyBAdHMtaWdub3JlXG4gICAgICBGc1JlcXVlc3QuZ2V0Lm1vY2tJbXBsZW1lbnRhdGlvbihtZXRob2RNb2NrZWQpO1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IG1ldGFkYXRhKG1vY2tlZFNlc3Npb24sICdmYWtlSGFuZGxlJywgeyBzaXplOiB0cnVlIH0pO1xuXG4gICAgICBleHBlY3QocmVzcCkudG9FcXVhbCh7IGhhbmRsZTogJ2Zha2VIYW5kbGUnIH0pO1xuICAgICAgZXhwZWN0KG1ldGhvZE1vY2tlZCkudG9IYXZlQmVlbkxhc3RDYWxsZWRXaXRoKCdmYWtlQXBpVXJsL2Zha2VIYW5kbGUvbWV0YWRhdGEnLCB7IHBhcmFtczogeyBzaXplOiB0cnVlIH0sIGZpbGVzdGFja0hlYWRlcnM6IGZhbHNlIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBvbiB3cm9uZyBvcHRpb24nLCBhc3luYyAoKSA9PiB7XG4gICAgICAvLyBAdHMtaWdub3JlXG4gICAgICByZXR1cm4gZXhwZWN0KCgpID0+IG1ldGFkYXRhKG1vY2tlZFNlc3Npb24sICdmYWtla2V5JywgeyBibGE6IDEyMyB9KSkudG9UaHJvd0Vycm9yKCdJbnZhbGlkIG1ldGFkYXRhIHBhcmFtcycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBhbiBlcnJvciBvbiBlbXB0eSBoYW5kbGUnLCAoKSA9PiB7XG4gICAgICByZXR1cm4gZXhwZWN0KCgpID0+IG1ldGFkYXRhKG1vY2tlZFNlc3Npb24pKS50b1Rocm93RXJyb3IoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVzcGVjdCBwcm92aWRlZCBzZWN1cml0eSBvcHRpb25zJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgZmFrZVNlY3VyaXR5ID0ge1xuICAgICAgICBzaWduYXR1cmU6ICdmYWtlUycsXG4gICAgICAgIHBvbGljeTogJ2Zha2VQJyxcbiAgICAgIH07XG5cbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIEZzUmVxdWVzdC5nZXQubW9ja0ltcGxlbWVudGF0aW9uKCgpID0+IFByb21pc2UucmVzb2x2ZSh7IGRhdGE6IHt9IH0pKTtcbiAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCBtZXRhZGF0YShtb2NrZWRTZXNzaW9uLCAnZmFrZUhhbmRsZScsIHt9LCBmYWtlU2VjdXJpdHkpO1xuXG4gICAgICBleHBlY3QocmVzcCkudG9FcXVhbCh7IGhhbmRsZTogJ2Zha2VIYW5kbGUnIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnRG93bmxvYWQnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gYnVmZmVyIG9uIGRvd25sb2FkIHJlcXVlc3QnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0ZXN0UmVzcCA9IEJ1ZmZlci5mcm9tKCcxMjMnKTtcbiAgICAgIGNvbnN0IG1ldGhvZE1vY2tlZCA9IGplc3QuZm4oKCkgPT4gUHJvbWlzZS5yZXNvbHZlKHRlc3RSZXNwKSk7XG5cbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIEZzUmVxdWVzdC5kaXNwYXRjaC5tb2NrSW1wbGVtZW50YXRpb24obWV0aG9kTW9ja2VkKTtcbiAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCBkb3dubG9hZChtb2NrZWRTZXNzaW9uLCAnZ05ETkNEV05US3FvR0ZJU2RkMkEnKTtcblxuICAgICAgZXhwZWN0KHJlc3ApLnRvRXF1YWwodGVzdFJlc3ApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnUmVtb3ZlJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgY2FsbCByZW1vdmUnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBkZWxldGVNb2NrZWQgPSBqZXN0LmZuKCgpID0+IFByb21pc2UucmVzb2x2ZSh7IGRhdGE6IHt9IH0pKTtcblxuICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgRnNSZXF1ZXN0LmRlbGV0ZS5tb2NrSW1wbGVtZW50YXRpb24oZGVsZXRlTW9ja2VkKTtcbiAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCByZW1vdmUoXG4gICAgICAgIE9iamVjdC5hc3NpZ24oe30sIG1vY2tlZFNlc3Npb24sIHtcbiAgICAgICAgICBzaWduYXR1cmU6ICdmYWtlUycsXG4gICAgICAgICAgcG9saWN5OiAnZmFrZVAnLFxuICAgICAgICB9KSxcbiAgICAgICAgJ2Zha2VIYW5kbGUnXG4gICAgICApO1xuXG4gICAgICBleHBlY3QocmVzcCkudG9FcXVhbCh7IGRhdGE6IHt9IH0pO1xuICAgICAgZXhwZWN0KGRlbGV0ZU1vY2tlZCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoJ2Zha2VBcGlVcmwvZmFrZUhhbmRsZScsIHsgcGFyYW1zOiB7IGtleTogJ2Zha2VBcGlrZXknLCBwb2xpY3k6ICdmYWtlUCcsIHNpZ25hdHVyZTogJ2Zha2VTJyB9LCBmaWxlc3RhY2tIZWFkZXJzOiBmYWxzZSB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVzcGVjdCBza2lwIHN0b3JhZ2Ugb3B0aW9uJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgbWV0aG9kTW9ja2VkID0gamVzdC5mbigoKSA9PiBQcm9taXNlLnJlc29sdmUoeyBkYXRhOiB7fSB9KSk7XG5cbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIEZzUmVxdWVzdC5kZWxldGUubW9ja0ltcGxlbWVudGF0aW9uKG1ldGhvZE1vY2tlZCk7XG4gICAgICBjb25zdCByZXNwID0gYXdhaXQgcmVtb3ZlKFxuICAgICAgICBPYmplY3QuYXNzaWduKHt9LCBtb2NrZWRTZXNzaW9uLCB7XG4gICAgICAgICAgc2lnbmF0dXJlOiAnZmFrZVMnLFxuICAgICAgICAgIHBvbGljeTogJ2Zha2VQJyxcbiAgICAgICAgfSksXG4gICAgICAgICdmYWtlSGFuZGxlJyxcbiAgICAgICAgdHJ1ZVxuICAgICAgKTtcblxuICAgICAgZXhwZWN0KHJlc3ApLnRvRXF1YWwoeyBkYXRhOiB7fSB9KTtcbiAgICAgIGV4cGVjdChtZXRob2RNb2NrZWQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKCdmYWtlQXBpVXJsL2Zha2VIYW5kbGUnLCB7IHBhcmFtczogeyBrZXk6ICdmYWtlQXBpa2V5JywgcG9saWN5OiAnZmFrZVAnLCBzaWduYXR1cmU6ICdmYWtlUycsIHNraXBfc3RvcmFnZTogdHJ1ZSB9LCBmaWxlc3RhY2tIZWFkZXJzOiBmYWxzZSB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgb24gZW1wdHkgaGFuZGxlJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KCgpID0+IHJlbW92ZShtb2NrZWRTZXNzaW9uKSkudG9UaHJvd0Vycm9yKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNhbGwgcmVtb3ZlIHdpdGggcHJvdmlkZWQgc2Vzc2lvbicsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGZha2VTZWN1cml0eSA9IHtcbiAgICAgICAgc2lnbmF0dXJlOiAnZmFrZVMnLFxuICAgICAgICBwb2xpY3k6ICdmYWtlUCcsXG4gICAgICB9O1xuXG4gICAgICAvLyBAdHMtaWdub3JlXG4gICAgICBGc1JlcXVlc3QuZGVsZXRlLm1vY2tJbXBsZW1lbnRhdGlvbigoKSA9PiBQcm9taXNlLnJlc29sdmUoeyBkYXRhOiB7fSB9KSk7XG4gICAgICBjb25zdCByZXNwID0gYXdhaXQgcmVtb3ZlKG1vY2tlZFNlc3Npb24sICdmYWtlSGFuZGxlJywgZmFsc2UsIGZha2VTZWN1cml0eSk7XG5cbiAgICAgIGV4cGVjdChyZXNwKS50b0VxdWFsKHsgZGF0YToge30gfSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IG9uIGVtcHR5IHNpZ25hdHVyZScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGZha2VTZWN1cml0eSA9IHtcbiAgICAgICAgc2lnbmF0dXJlOiBudWxsLFxuICAgICAgICBwb2xpY3k6ICdmYWtlUCcsXG4gICAgICB9O1xuXG4gICAgICBleHBlY3QoKCkgPT4gcmVtb3ZlKG1vY2tlZFNlc3Npb24sICdmYWtlSGFuZGxlJywgZmFsc2UsIGZha2VTZWN1cml0eSkpLnRvVGhyb3dFcnJvcigpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBvbiBlbXB0eSBwb2xpY3knLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBmYWtlU2VjdXJpdHkgPSB7XG4gICAgICAgIHNpZ25hdHVyZTogJ2Zha2VTJyxcbiAgICAgICAgcG9saWN5OiBudWxsLFxuICAgICAgfTtcblxuICAgICAgZXhwZWN0KCgpID0+IHJlbW92ZShtb2NrZWRTZXNzaW9uLCAnZmFrZUhhbmRsZScsIGZhbHNlLCBmYWtlU2VjdXJpdHkpKS50b1Rocm93RXJyb3IoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgb24gZW1wdHkgcG9saWN5IG9uIHNlc3Npb24nLCBhc3luYyAoKSA9PiB7XG4gICAgICByZXR1cm4gZXhwZWN0KCgpID0+IHJlbW92ZShtb2NrZWRTZXNzaW9uLCAnZmFrZUhhbmRsZScpKS50b1Rocm93RXJyb3IoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1JldHJpZXZlJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgbWFrZSBjb3JyZWN0IHJldHJpZXZlIHJlcXVlc3QgKEdFVCknLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBtZXRob2RNb2NrZWQgPSBqZXN0LmZuKCgpID0+IFByb21pc2UucmVzb2x2ZSh7IGRhdGE6IHt9IH0pKTtcblxuICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgRnNSZXF1ZXN0LmRpc3BhdGNoLm1vY2tJbXBsZW1lbnRhdGlvbihtZXRob2RNb2NrZWQpO1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHJldHJpZXZlKG1vY2tlZFNlc3Npb24sICdmYWtlSGFuZGxlJyk7XG5cbiAgICAgIGV4cGVjdChyZXNwKS50b0VxdWFsKHt9KTtcbiAgICAgIGV4cGVjdChtZXRob2RNb2NrZWQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKCdmYWtlQXBpVXJsL2Zha2VIYW5kbGUnLCB7IG1ldGhvZDogJ0dFVCcsIHBhcmFtczogeyBrZXk6ICdmYWtlQXBpa2V5JyB9LCBmaWxlc3RhY2tIZWFkZXJzOiBmYWxzZSB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgbWFrZSBjb3JyZWN0IHJldHJpZXZlIHJlcXVlc3QgKEhFQUQpJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgbWV0aG9kTW9ja2VkID0gamVzdC5mbigoKSA9PiBQcm9taXNlLnJlc29sdmUoeyBkYXRhOiB7fSwgaGVhZGVyczogeyB0eXBlOiAndGVzdCcgfSB9KSk7XG5cbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIEZzUmVxdWVzdC5kaXNwYXRjaC5tb2NrSW1wbGVtZW50YXRpb24obWV0aG9kTW9ja2VkKTtcbiAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCByZXRyaWV2ZShtb2NrZWRTZXNzaW9uLCAnZmFrZUhhbmRsZScsIHtcbiAgICAgICAgaGVhZDogdHJ1ZSxcbiAgICAgIH0pO1xuXG4gICAgICBleHBlY3QocmVzcCkudG9FcXVhbCh7IHR5cGU6ICd0ZXN0JyB9KTtcbiAgICAgIGV4cGVjdChtZXRob2RNb2NrZWQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKCdmYWtlQXBpVXJsL2Zha2VIYW5kbGUnLCB7IG1ldGhvZDogJ0hFQUQnLCBwYXJhbXM6IHsga2V5OiAnZmFrZUFwaWtleScgfSwgZmlsZXN0YWNrSGVhZGVyczogZmFsc2UgfSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIG1ha2UgY29ycmVjdCByZXRyaWV2ZSByZXF1ZXN0IHdpdGggcHJvdmlkZWQgc2VjdXJpdHknLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBtZXRob2RNb2NrZWQgPSBqZXN0LmZuKCgpID0+IFByb21pc2UucmVzb2x2ZSh7IGRhdGE6IHt9IH0pKTtcblxuICAgICAgY29uc3QgZmFrZVNlY3VyaXR5ID0ge1xuICAgICAgICBzaWduYXR1cmU6ICdmYWtlUycsXG4gICAgICAgIHBvbGljeTogJ2Zha2VQJyxcbiAgICAgIH07XG5cbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIEZzUmVxdWVzdC5kaXNwYXRjaC5tb2NrSW1wbGVtZW50YXRpb24obWV0aG9kTW9ja2VkKTtcbiAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCByZXRyaWV2ZShtb2NrZWRTZXNzaW9uLCAnZmFrZUhhbmRsZScsIHt9LCBmYWtlU2VjdXJpdHkpO1xuXG4gICAgICBleHBlY3QocmVzcCkudG9FcXVhbCh7fSk7XG4gICAgICBleHBlY3QobWV0aG9kTW9ja2VkKS50b0hhdmVCZWVuQ2FsbGVkV2l0aCgnZmFrZUFwaVVybC9mYWtlSGFuZGxlJywge1xuICAgICAgICBtZXRob2Q6ICdHRVQnLFxuICAgICAgICBwYXJhbXM6IHsga2V5OiAnZmFrZUFwaWtleScsIHBvbGljeTogJ2Zha2VQJywgc2lnbmF0dXJlOiAnZmFrZVMnIH0sXG4gICAgICAgIGZpbGVzdGFja0hlYWRlcnM6IGZhbHNlLFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIG1ha2UgY29ycmVjdCByZXRyaWV2ZSByZXF1ZXN0IHdpdGggZXh0ZW5zaW9uJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgbWV0aG9kTW9ja2VkID0gamVzdC5mbigoKSA9PiBQcm9taXNlLnJlc29sdmUoeyBkYXRhOiB7fSB9KSk7XG5cbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIEZzUmVxdWVzdC5kaXNwYXRjaC5tb2NrSW1wbGVtZW50YXRpb24obWV0aG9kTW9ja2VkKTtcbiAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCByZXRyaWV2ZShtb2NrZWRTZXNzaW9uLCAnZmFrZUhhbmRsZScsIHtcbiAgICAgICAgZXh0ZW5zaW9uOiAndHh0JyxcbiAgICAgIH0pO1xuXG4gICAgICBleHBlY3QocmVzcCkudG9FcXVhbCh7fSk7XG4gICAgICBleHBlY3QobWV0aG9kTW9ja2VkKS50b0hhdmVCZWVuQ2FsbGVkV2l0aCgnZmFrZUFwaVVybC9mYWtlSGFuZGxlK3R4dCcsIHsgbWV0aG9kOiAnR0VUJywgcGFyYW1zOiB7IGtleTogJ2Zha2VBcGlrZXknIH0sIGZpbGVzdGFja0hlYWRlcnM6IGZhbHNlIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBtYWtlIGNvcnJlY3QgcmV0cmlldmUgcmVxdWVzdCB3aXRoIG1ldGFkYXRhJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgbWV0aG9kTW9ja2VkID0gamVzdC5mbigoKSA9PiBQcm9taXNlLnJlc29sdmUoeyBkYXRhOiB7fSB9KSk7XG5cbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIEZzUmVxdWVzdC5kaXNwYXRjaC5tb2NrSW1wbGVtZW50YXRpb24obWV0aG9kTW9ja2VkKTtcbiAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCByZXRyaWV2ZShtb2NrZWRTZXNzaW9uLCAnZmFrZUhhbmRsZScsIHtcbiAgICAgICAgbWV0YWRhdGE6IHRydWUsXG4gICAgICB9KTtcblxuICAgICAgZXhwZWN0KHJlc3ApLnRvRXF1YWwoe30pO1xuICAgICAgZXhwZWN0KG1ldGhvZE1vY2tlZCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoJ2Zha2VBcGlVcmwvZmFrZUhhbmRsZS9tZXRhZGF0YScsIHsgbWV0aG9kOiAnR0VUJywgcGFyYW1zOiB7IGtleTogJ2Zha2VBcGlrZXknIH0sIGZpbGVzdGFja0hlYWRlcnM6IGZhbHNlIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBhbiBlcnJvciBvbiBlbXB0eSBoYW5kbGUnLCAoKSA9PiB7XG4gICAgICByZXR1cm4gZXhwZWN0KCgpID0+IHJldHJpZXZlKG1vY2tlZFNlc3Npb24sICcnKSkudG9UaHJvd0Vycm9yKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGFuIGVycm9yIHdvcm5nIG9wdGlvbnMgcHJvdmlkZWQnLCAoKSA9PiB7XG4gICAgICByZXR1cm4gZXhwZWN0KCgpID0+XG4gICAgICAgIHJldHJpZXZlKG1vY2tlZFNlc3Npb24sICdmYWtlSGFuZGxlJywge1xuICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICB0ZXN0OiAxMjMsXG4gICAgICAgIH0pXG4gICAgICApLnRvVGhyb3dFcnJvcignSW52YWxpZCByZXRyaWV2ZSBwYXJhbXMnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgbm90IHRocm93IGFuIGVycm9yIHdvcm5nIG9wdGlvbnMgcHJvdmlkZWQnLCAoKSA9PiB7XG4gICAgICByZXR1cm4gZXhwZWN0KCgpID0+XG4gICAgICAgIHJldHJpZXZlKG1vY2tlZFNlc3Npb24sICdmYWtlSGFuZGxlJywge1xuICAgICAgICAgIG1ldGFkYXRhOiB0cnVlLFxuICAgICAgICB9KVxuICAgICAgKS5ub3QudG9UaHJvd0Vycm9yKCdJbnZhbGlkIHJldHJpZXZlIHBhcmFtcycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBhbiBlcnJvciB3aGVuIG1ldGFkYXRhIGFuZCBoZWFkIGlzIHByb3ZpZGVkJywgKCkgPT4ge1xuICAgICAgcmV0dXJuIGV4cGVjdCgoKSA9PlxuICAgICAgICByZXRyaWV2ZShtb2NrZWRTZXNzaW9uLCAnZmFrZUhhbmRsZScsIHtcbiAgICAgICAgICBtZXRhZGF0YTogdHJ1ZSxcbiAgICAgICAgICBoZWFkOiB0cnVlLFxuICAgICAgICB9KVxuICAgICAgKS50b1Rocm93RXJyb3IoKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==