UNPKG

filestack-js

Version:

Official JavaScript library for Filestack

212 lines (210 loc) 30.1 kB
/* * Copyright (c) 2019 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 { resolveCdnUrl, resolveHost, removeEmpty, uniqueTime, uniqueId, md5, extensionToMime, sanitizeName, filterObject, b64, getVersion, cleanUpCallbacks } from './index'; import { config } from '../../config'; var v = require('../../../../package.json').version; describe('utils:index', function () { describe('resolveCdnUrl', function () { var session = { apikey: 'TEST_API_KEY', cname: 'example.com', urls: config.urls, }; it('should properly resolve cdn url with hashed handle', function () { var handle = '5aYkEQJSQCmYShsoCnZN'; var result = resolveCdnUrl(session, handle); expect(result).toEqual('https://cdn.filestackcontent.com'); }); it('should properly resolve cdn url with src handle', function () { var handle = 'src://test123/test.jpg'; var result = resolveCdnUrl(session, handle); expect(result).toEqual('https://cdn.filestackcontent.com/TEST_API_KEY'); }); it('should properly resolve cdn url with hashed handle', function () { var handle = 'https://static1.squarespace.com/static/544eb3cce4b0ef091773611f/t/59ba7ce1bd10f00dcdc80a5f/1505394087367/DSC_0527.jpg'; var result = resolveCdnUrl(session, handle); expect(result).toEqual('https://cdn.filestackcontent.com/TEST_API_KEY'); }); it('should throw an error when using src handle or url without apikey', function () { var handle = 'src://test123/test.jpg'; session.apikey = ''; expect(function () { resolveCdnUrl(session, handle); }).toThrow('Api key is required when storage alias is provided'); }); }); describe('resolveHost', function () { var hosts = config.urls; var checkHosts = function (hosts, expected) { Object.keys(hosts).forEach(function (k) { expect(hosts[k].indexOf(expected) > -1).toBeTruthy(); }); }; it('should return proper host', function () { var cname = 'example.com'; var result = resolveHost(hosts, cname); checkHosts(result, cname); }); it('should return hosts when cname is an empty string', function () { var cname = ''; var result = resolveHost(hosts, cname); checkHosts(result, cname); }); it('should be idempotent', function () { var cname = 'stage.filestackapi.com'; var firstResult = resolveHost(hosts, cname); var copiedResult = JSON.parse(JSON.stringify(firstResult)); var secondResult = resolveHost(copiedResult, cname); expect(JSON.stringify(firstResult)).toEqual(JSON.stringify(secondResult)); }); }); describe('removeEmpty', function () { it('should remove empty options from an object', function () { var testOb = { test1: true, test2: undefined, test3: false }; expect(removeEmpty(testOb)).toEqual({ test1: true, test3: false }); }); }); describe('uniqueTime', function () { it('should return unique times', function () { expect(uniqueTime()).not.toEqual(uniqueTime()); }); }); describe('uniqueId', function () { it('should get different ids each time', function () { expect(uniqueId()).not.toEqual(uniqueId()); }); it('should return id with given length', function () { expect(uniqueId(12).length).toEqual(12); expect(uniqueId(4).length).toEqual(4); }); }); describe('md5', function () { it('should return correct md5 value', function () { expect(md5(Buffer.from('test'))).toEqual('CY9rzUYh03PK3k6DJie09g=='); }); }); describe('getVersion', function () { it('should return correct version from package json', function () { expect(getVersion()).toEqual("JS-".concat(v)); }); }); describe('b64', function () { it('should return correct b65 value', function () { expect(b64('testtext')).toEqual('dGVzdHRleHQ='); }); it('should escape chars to make b64 url safe string - char "/"', function () { expect(b64('*0eijATh#"I$PR)s<uTa}{t>E"LC:L', true)).toEqual('KjBlaWpBVGgjIkkkUFIpczx1VGF9e3Q-RSJMQzpM'); }); it('should escape chars to make b64 url safe string - char ""', function () { expect(b64('W{wpB@ckYD0O@&?!||9PS)7^+F*H8N', true)).toEqual('V3t3cEJAY2tZRDBPQCY_IXx8OVBTKTdeK0YqSDhO'); }); }); describe('sanitizeName', function () { it('should sanitize file name with extension', function () { expect(sanitizeName('a\\{%`"~[]#|^<>1.jpg')).toEqual('a-------------1.jpg'); }); it('should sanitize file name without extension', function () { expect(sanitizeName('123qwe')).toEqual('123qwe'); }); it('should return undefined on empty string', function () { expect(sanitizeName('')).toEqual('undefined'); }); it('should respect sanitize options as boolean', function () { expect(sanitizeName('[]#|.jpg', false)).toEqual('[]#|.jpg'); }); it('should not change dots in filename', function () { expect(sanitizeName('[]#some.tar.gz', false)).toEqual('[]#some.tar.gz'); }); it('should respect sanitize options with provided options', function () { expect(sanitizeName('[]#|.jpg', { exclude: ['[', ']'], replacement: '_', })).toEqual('__#|.jpg'); }); }); describe('filterObject', function () { it('should filter object', function () { expect(filterObject({ test: 1, test2: 2, test3: 3, }, ['test', 'test2'])).toEqual({ test: 1, test2: 2, }); }); it('should result the same object on empty requirements', function () { expect(filterObject({ test: 1, test2: 2, test3: 3, }, [])).toEqual({ test: 1, test2: 2, test3: 3, }); }); it('should not throw on empty filtered object', function () { expect(filterObject({}, ['test'])).toEqual({}); }); }); describe('extensionToMime', function () { it('should return mimetype if mime is passed', function () { expect(extensionToMime('')).toEqual(undefined); }); it('should return same mime is passed', function () { expect(extensionToMime('image/png')).toEqual('image/png'); expect(extensionToMime('image/jpg')).toEqual('image/jpg'); expect(extensionToMime('application/pdf')).toEqual('application/pdf'); }); it('it should return correct mimes for ext', function () { expect(extensionToMime('.png')).toEqual('image/png'); expect(extensionToMime('.jpg')).toEqual('image/jpeg'); expect(extensionToMime('.pdf')).toEqual('application/pdf'); expect(extensionToMime('.key')).toEqual('application/vnd.apple.keynote'); expect(extensionToMime('.zip')).toEqual('application/zip'); expect(extensionToMime('.numbers')).toEqual('application/vnd.apple.numbers'); }); it('it should extract extensions form filename or ext with dot', function () { expect(extensionToMime('test.png')).toEqual('image/png'); expect(extensionToMime('test.jpg')).toEqual('image/jpeg'); expect(extensionToMime('test.pdf')).toEqual('application/pdf'); }); }); describe('CleanupCallbacks', function () { it('should set callbacks as undefined and return untouched object', function () { var testObj = { fn: function () { return 1; }, test: { fn2: function () { return 2; }, }, testN: 123, tests: 'string', testObj: { tst: 123, }, }; expect(cleanUpCallbacks(testObj)).toEqual({ test: {}, testN: 123, tests: 'string', testObj: { tst: 123, }, }); }); }); }); //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvdXRpbHMvaW5kZXguc3BlYy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFDSCxPQUFPLEVBQUUsYUFBYSxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUUsZUFBZSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsR0FBRyxFQUFFLFVBQVUsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUM3SyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3RDLElBQU0sQ0FBQyxHQUFHLE9BQU8sQ0FBQywwQkFBMEIsQ0FBQyxDQUFDLE9BQU8sQ0FBQztBQUV0RCxRQUFRLENBQUMsYUFBYSxFQUFFO0lBQ3RCLFFBQVEsQ0FBQyxlQUFlLEVBQUU7UUFFeEIsSUFBTSxPQUFPLEdBQUc7WUFDZCxNQUFNLEVBQUUsY0FBYztZQUN0QixLQUFLLEVBQUUsYUFBYTtZQUNwQixJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUk7U0FDbEIsQ0FBQztRQUVGLEVBQUUsQ0FBQyxvREFBb0QsRUFBRTtZQUN2RCxJQUFNLE1BQU0sR0FBRyxzQkFBc0IsQ0FBQztZQUN0QyxJQUFNLE1BQU0sR0FBRyxhQUFhLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzlDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLENBQUMsa0NBQWtDLENBQUMsQ0FBQztRQUM3RCxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxpREFBaUQsRUFBRTtZQUNwRCxJQUFNLE1BQU0sR0FBRyx3QkFBd0IsQ0FBQztZQUN4QyxJQUFNLE1BQU0sR0FBRyxhQUFhLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzlDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLENBQUMsK0NBQStDLENBQUMsQ0FBQztRQUMxRSxDQUFDLENBQUMs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QUNUO2FBQ0YsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwiZmlsZSI6ImxpYi91dGlscy9pbmRleC5zcGVjLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoYykgMjAxOSBieSBGaWxlc3RhY2suXG4gKiBTb21lIHJpZ2h0cyByZXNlcnZlZC5cbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cbmltcG9ydCB7IHJlc29sdmVDZG5VcmwsIHJlc29sdmVIb3N0LCByZW1vdmVFbXB0eSwgdW5pcXVlVGltZSwgdW5pcXVlSWQsIG1kNSwgZXh0ZW5zaW9uVG9NaW1lLCBzYW5pdGl6ZU5hbWUsIGZpbHRlck9iamVjdCwgYjY0LCBnZXRWZXJzaW9uLCBjbGVhblVwQ2FsbGJhY2tzIH0gZnJvbSAnLi9pbmRleCc7XG5pbXBvcnQgeyBjb25maWcgfSBmcm9tICcuLi8uLi9jb25maWcnO1xuY29uc3QgdiA9IHJlcXVpcmUoJy4uLy4uLy4uLy4uL3BhY2thZ2UuanNvbicpLnZlcnNpb247XG5cbmRlc2NyaWJlKCd1dGlsczppbmRleCcsICgpID0+IHtcbiAgZGVzY3JpYmUoJ3Jlc29sdmVDZG5VcmwnLCAoKSA9PiB7XG5cbiAgICBjb25zdCBzZXNzaW9uID0ge1xuICAgICAgYXBpa2V5OiAnVEVTVF9BUElfS0VZJyxcbiAgICAgIGNuYW1lOiAnZXhhbXBsZS5jb20nLFxuICAgICAgdXJsczogY29uZmlnLnVybHMsXG4gICAgfTtcblxuICAgIGl0KCdzaG91bGQgcHJvcGVybHkgcmVzb2x2ZSBjZG4gdXJsIHdpdGggaGFzaGVkIGhhbmRsZScsICgpID0+IHtcbiAgICAgIGNvbnN0IGhhbmRsZSA9ICc1YVlrRVFKU1FDbVlTaHNvQ25aTic7XG4gICAgICBjb25zdCByZXN1bHQgPSByZXNvbHZlQ2RuVXJsKHNlc3Npb24sIGhhbmRsZSk7XG4gICAgICBleHBlY3QocmVzdWx0KS50b0VxdWFsKCdodHRwczovL2Nkbi5maWxlc3RhY2tjb250ZW50LmNvbScpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwcm9wZXJseSByZXNvbHZlIGNkbiB1cmwgd2l0aCBzcmMgaGFuZGxlJywgKCkgPT4ge1xuICAgICAgY29uc3QgaGFuZGxlID0gJ3NyYzovL3Rlc3QxMjMvdGVzdC5qcGcnO1xuICAgICAgY29uc3QgcmVzdWx0ID0gcmVzb2x2ZUNkblVybChzZXNzaW9uLCBoYW5kbGUpO1xuICAgICAgZXhwZWN0KHJlc3VsdCkudG9FcXVhbCgnaHR0cHM6Ly9jZG4uZmlsZXN0YWNrY29udGVudC5jb20vVEVTVF9BUElfS0VZJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHByb3Blcmx5IHJlc29sdmUgY2RuIHVybCB3aXRoIGhhc2hlZCBoYW5kbGUnLCAoKSA9PiB7XG4gICAgICBjb25zdCBoYW5kbGUgPSAnaHR0cHM6Ly9zdGF0aWMxLnNxdWFyZXNwYWNlLmNvbS9zdGF0aWMvNTQ0ZWIzY2NlNGIwZWYwOTE3NzM2MTFmL3QvNTliYTdjZTFiZDEwZjAwZGNkYzgwYTVmLzE1MDUzOTQwODczNjcvRFNDXzA1MjcuanBnJztcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHJlc29sdmVDZG5Vcmwoc2Vzc2lvbiwgaGFuZGxlKTtcbiAgICAgIGV4cGVjdChyZXN1bHQpLnRvRXF1YWwoJ2h0dHBzOi8vY2RuLmZpbGVzdGFja2NvbnRlbnQuY29tL1RFU1RfQVBJX0tFWScpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBhbiBlcnJvciB3aGVuIHVzaW5nIHNyYyBoYW5kbGUgb3IgdXJsIHdpdGhvdXQgYXBpa2V5JywgKCkgPT4ge1xuICAgICAgY29uc3QgaGFuZGxlID0gJ3NyYzovL3Rlc3QxMjMvdGVzdC5qcGcnO1xuICAgICAgc2Vzc2lvbi5hcGlrZXkgPSAnJztcbiAgICAgIGV4cGVjdCgoKSA9PiB7IHJlc29sdmVDZG5Vcmwoc2Vzc2lvbiwgaGFuZGxlKTsgfSkudG9UaHJvdygnQXBpIGtleSBpcyByZXF1aXJlZCB3aGVuIHN0b3JhZ2UgYWxpYXMgaXMgcHJvdmlkZWQnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3Jlc29sdmVIb3N0JywgKCkgPT4ge1xuICAgIGNvbnN0IGhvc3RzID0gY29uZmlnLnVybHM7XG5cbiAgICBjb25zdCBjaGVja0hvc3RzID0gKGhvc3RzLCBleHBlY3RlZCkgPT4ge1xuICAgICAgT2JqZWN0LmtleXMoaG9zdHMpLmZvckVhY2goKGspID0+IHtcbiAgICAgICAgZXhwZWN0KGhvc3RzW2tdLmluZGV4T2YoZXhwZWN0ZWQpID4gLTEpLnRvQmVUcnV0aHkoKTtcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBwcm9wZXIgaG9zdCcsICgpID0+IHtcbiAgICAgIGNvbnN0IGNuYW1lID0gJ2V4YW1wbGUuY29tJztcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHJlc29sdmVIb3N0KGhvc3RzLCBjbmFtZSk7XG4gICAgICBjaGVja0hvc3RzKHJlc3VsdCwgY25hbWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gaG9zdHMgd2hlbiBjbmFtZSBpcyBhbiBlbXB0eSBzdHJpbmcnLCAoKSA9PiB7XG4gICAgICBjb25zdCBjbmFtZSA9ICcnO1xuICAgICAgY29uc3QgcmVzdWx0ID0gcmVzb2x2ZUhvc3QoaG9zdHMsIGNuYW1lKTtcbiAgICAgIGNoZWNrSG9zdHMocmVzdWx0LCBjbmFtZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJlIGlkZW1wb3RlbnQnLCAoKSA9PiB7XG4gICAgICBjb25zdCBjbmFtZSA9ICdzdGFnZS5maWxlc3RhY2thcGkuY29tJztcbiAgICAgIGNvbnN0IGZpcnN0UmVzdWx0ID0gcmVzb2x2ZUhvc3QoaG9zdHMsIGNuYW1lKTtcbiAgICAgIGNvbnN0IGNvcGllZFJlc3VsdCA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoZmlyc3RSZXN1bHQpKTtcbiAgICAgIGNvbnN0IHNlY29uZFJlc3VsdCA9IHJlc29sdmVIb3N0KGNvcGllZFJlc3VsdCwgY25hbWUpO1xuXG4gICAgICBleHBlY3QoSlNPTi5zdHJpbmdpZnkoZmlyc3RSZXN1bHQpKS50b0VxdWFsKEpTT04uc3RyaW5naWZ5KHNlY29uZFJlc3VsdCkpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgncmVtb3ZlRW1wdHknLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCByZW1vdmUgZW1wdHkgb3B0aW9ucyBmcm9tIGFuIG9iamVjdCcsICgpID0+IHtcbiAgICAgIGNvbnN0IHRlc3RPYiA9IHsgdGVzdDE6IHRydWUsIHRlc3QyOiB1bmRlZmluZWQsIHRlc3QzOiBmYWxzZSB9O1xuICAgICAgZXhwZWN0KHJlbW92ZUVtcHR5KHRlc3RPYikpLnRvRXF1YWwoeyB0ZXN0MTogdHJ1ZSwgdGVzdDM6IGZhbHNlIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgndW5pcXVlVGltZScsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHJldHVybiB1bmlxdWUgdGltZXMnLCAoKSA9PiB7XG4gICAgICBleHBlY3QodW5pcXVlVGltZSgpKS5ub3QudG9FcXVhbCh1bmlxdWVUaW1lKCkpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgndW5pcXVlSWQnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBnZXQgZGlmZmVyZW50IGlkcyBlYWNoIHRpbWUnLCAoKSA9PiB7XG4gICAgICBleHBlY3QodW5pcXVlSWQoKSkubm90LnRvRXF1YWwodW5pcXVlSWQoKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBpZCB3aXRoIGdpdmVuIGxlbmd0aCcsICgpID0+IHtcbiAgICAgIGV4cGVjdCh1bmlxdWVJZCgxMikubGVuZ3RoKS50b0VxdWFsKDEyKTtcbiAgICAgIGV4cGVjdCh1bmlxdWVJZCg0KS5sZW5ndGgpLnRvRXF1YWwoNCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdtZDUnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gY29ycmVjdCBtZDUgdmFsdWUnLCAoKSA9PiB7XG4gICAgICBleHBlY3QobWQ1KEJ1ZmZlci5mcm9tKCd0ZXN0JykpKS50b0VxdWFsKCdDWTlyelVZaDAzUEszazZESmllMDlnPT0nKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2dldFZlcnNpb24nLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gY29ycmVjdCB2ZXJzaW9uIGZyb20gcGFja2FnZSBqc29uJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KGdldFZlcnNpb24oKSkudG9FcXVhbChgSlMtJHt2fWApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnYjY0JywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgcmV0dXJuIGNvcnJlY3QgYjY1IHZhbHVlJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KGI2NCgndGVzdHRleHQnKSkudG9FcXVhbCgnZEdWemRIUmxlSFE9Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGVzY2FwZSBjaGFycyB0byBtYWtlIGI2NCB1cmwgc2FmZSBzdHJpbmcgLSBjaGFyIFwiL1wiJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KGI2NCgnKjBlaWpBVGgjXCJJJFBSKXM8dVRhfXt0PkVcIkxDOkwnLCB0cnVlKSkudG9FcXVhbCgnS2pCbGFXcEJWR2dqSWtra1VGSXBjengxVkdGOWUzUS1SU0pNUXpwTScpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBlc2NhcGUgY2hhcnMgdG8gbWFrZSBiNjQgdXJsIHNhZmUgc3RyaW5nIC0gY2hhciBcIlwiJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KGI2NCgnV3t3cEJAY2tZRDBPQCY/IXx8OVBTKTdeK0YqSDhOJywgdHJ1ZSkpLnRvRXF1YWwoJ1YzdDNjRUpBWTJ0WlJEQlBRQ1lfSVh4OE9WQlRLVGRlSzBZcVNEaE8nKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3Nhbml0aXplTmFtZScsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHNhbml0aXplIGZpbGUgbmFtZSB3aXRoIGV4dGVuc2lvbicsICgpID0+IHtcbiAgICAgIGV4cGVjdChzYW5pdGl6ZU5hbWUoJ2FcXFxceyVgXCJ+W10jfF48PjEuanBnJykpLnRvRXF1YWwoJ2EtLS0tLS0tLS0tLS0tMS5qcGcnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc2FuaXRpemUgZmlsZSBuYW1lIHdpdGhvdXQgZXh0ZW5zaW9uJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KHNhbml0aXplTmFtZSgnMTIzcXdlJykpLnRvRXF1YWwoJzEyM3F3ZScpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdW5kZWZpbmVkIG9uIGVtcHR5IHN0cmluZycsICgpID0+IHtcbiAgICAgIGV4cGVjdChzYW5pdGl6ZU5hbWUoJycpKS50b0VxdWFsKCd1bmRlZmluZWQnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVzcGVjdCBzYW5pdGl6ZSBvcHRpb25zIGFzIGJvb2xlYW4nLCAoKSA9PiB7XG4gICAgICBleHBlY3Qoc2FuaXRpemVOYW1lKCdbXSN8LmpwZycsIGZhbHNlKSkudG9FcXVhbCgnW10jfC5qcGcnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgbm90IGNoYW5nZSBkb3RzIGluIGZpbGVuYW1lJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KHNhbml0aXplTmFtZSgnW10jc29tZS50YXIuZ3onLCBmYWxzZSkpLnRvRXF1YWwoJ1tdI3NvbWUudGFyLmd6Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlc3BlY3Qgc2FuaXRpemUgb3B0aW9ucyB3aXRoIHByb3ZpZGVkIG9wdGlvbnMnLCAoKSA9PiB7XG4gICAgICBleHBlY3Qoc2FuaXRpemVOYW1lKCdbXSN8LmpwZycsIHtcbiAgICAgICAgZXhjbHVkZTogWydbJywgJ10nXSxcbiAgICAgICAgcmVwbGFjZW1lbnQ6ICdfJyxcbiAgICAgIH0pKS50b0VxdWFsKCdfXyN8LmpwZycpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnZmlsdGVyT2JqZWN0JywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgZmlsdGVyIG9iamVjdCcsICgpID0+IHtcbiAgICAgIGV4cGVjdChmaWx0ZXJPYmplY3Qoe1xuICAgICAgICB0ZXN0OiAxLFxuICAgICAgICB0ZXN0MjogMixcbiAgICAgICAgdGVzdDM6IDMsXG4gICAgICB9LCBbJ3Rlc3QnLCAndGVzdDInXSkpLnRvRXF1YWwoe1xuICAgICAgICB0ZXN0OiAxLFxuICAgICAgICB0ZXN0MjogMixcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXN1bHQgdGhlIHNhbWUgb2JqZWN0IG9uIGVtcHR5IHJlcXVpcmVtZW50cycsICgpID0+IHtcbiAgICAgIGV4cGVjdChmaWx0ZXJPYmplY3Qoe1xuICAgICAgICB0ZXN0OiAxLFxuICAgICAgICB0ZXN0MjogMixcbiAgICAgICAgdGVzdDM6IDMsXG4gICAgICB9LCBbXSkpLnRvRXF1YWwoe1xuICAgICAgICB0ZXN0OiAxLFxuICAgICAgICB0ZXN0MjogMixcbiAgICAgICAgdGVzdDM6IDMsXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgbm90IHRocm93IG9uIGVtcHR5IGZpbHRlcmVkIG9iamVjdCcsICgpID0+IHtcbiAgICAgIGV4cGVjdChmaWx0ZXJPYmplY3Qoe30sIFsndGVzdCddKSkudG9FcXVhbCh7fSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdleHRlbnNpb25Ub01pbWUnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gbWltZXR5cGUgaWYgbWltZSBpcyBwYXNzZWQnLCAoKSA9PiB7XG4gICAgICBleHBlY3QoZXh0ZW5zaW9uVG9NaW1lKCcnKSkudG9FcXVhbCh1bmRlZmluZWQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gc2FtZSBtaW1lIGlzIHBhc3NlZCcsICgpID0+IHtcbiAgICAgIGV4cGVjdChleHRlbnNpb25Ub01pbWUoJ2ltYWdlL3BuZycpKS50b0VxdWFsKCdpbWFnZS9wbmcnKTtcbiAgICAgIGV4cGVjdChleHRlbnNpb25Ub01pbWUoJ2ltYWdlL2pwZycpKS50b0VxdWFsKCdpbWFnZS9qcGcnKTtcbiAgICAgIGV4cGVjdChleHRlbnNpb25Ub01pbWUoJ2FwcGxpY2F0aW9uL3BkZicpKS50b0VxdWFsKCdhcHBsaWNhdGlvbi9wZGYnKTtcbiAgICB9KTtcblxuICAgIGl0KCdpdCBzaG91bGQgcmV0dXJuIGNvcnJlY3QgbWltZXMgZm9yIGV4dCcsICgpID0+IHtcbiAgICAgIGV4cGVjdChleHRlbnNpb25Ub01pbWUoJy5wbmcnKSkudG9FcXVhbCgnaW1hZ2UvcG5nJyk7XG4gICAgICBleHBlY3QoZXh0ZW5zaW9uVG9NaW1lKCcuanBnJykpLnRvRXF1YWwoJ2ltYWdlL2pwZWcnKTtcbiAgICAgIGV4cGVjdChleHRlbnNpb25Ub01pbWUoJy5wZGYnKSkudG9FcXVhbCgnYXBwbGljYXRpb24vcGRmJyk7XG5cbiAgICAgIGV4cGVjdChleHRlbnNpb25Ub01pbWUoJy5rZXknKSkudG9FcXVhbCgnYXBwbGljYXRpb24vdm5kLmFwcGxlLmtleW5vdGUnKTtcbiAgICAgIGV4cGVjdChleHRlbnNpb25Ub01pbWUoJy56aXAnKSkudG9FcXVhbCgnYXBwbGljYXRpb24vemlwJyk7XG4gICAgICBleHBlY3QoZXh0ZW5zaW9uVG9NaW1lKCcubnVtYmVycycpKS50b0VxdWFsKCdhcHBsaWNhdGlvbi92bmQuYXBwbGUubnVtYmVycycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2l0IHNob3VsZCBleHRyYWN0IGV4dGVuc2lvbnMgZm9ybSBmaWxlbmFtZSBvciBleHQgd2l0aCBkb3QnLCAoKSA9PiB7XG4gICAgICBleHBlY3QoZXh0ZW5zaW9uVG9NaW1lKCd0ZXN0LnBuZycpKS50b0VxdWFsKCdpbWFnZS9wbmcnKTtcbiAgICAgIGV4cGVjdChleHRlbnNpb25Ub01pbWUoJ3Rlc3QuanBnJykpLnRvRXF1YWwoJ2ltYWdlL2pwZWcnKTtcbiAgICAgIGV4cGVjdChleHRlbnNpb25Ub01pbWUoJ3Rlc3QucGRmJykpLnRvRXF1YWwoJ2FwcGxpY2F0aW9uL3BkZicpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnQ2xlYW51cENhbGxiYWNrcycsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHNldCBjYWxsYmFja3MgYXMgdW5kZWZpbmVkIGFuZCByZXR1cm4gdW50b3VjaGVkIG9iamVjdCcsICgpID0+IHtcbiAgICAgIGNvbnN0IHRlc3RPYmogPSB7XG4gICAgICAgIGZuOiAoKSA9PiAxLFxuICAgICAgICB0ZXN0OiB7XG4gICAgICAgICAgZm4yOiAoKSA9PiAyLFxuICAgICAgICB9LFxuICAgICAgICB0ZXN0TjogMTIzLFxuICAgICAgICB0ZXN0czogJ3N0cmluZycsXG4gICAgICAgIHRlc3RPYmo6IHtcbiAgICAgICAgICB0c3Q6IDEyMyxcbiAgICAgICAgfSxcbiAgICAgIH07XG5cbiAgICAgIGV4cGVjdChjbGVhblVwQ2FsbGJhY2tzKHRlc3RPYmopKS50b0VxdWFsKHtcbiAgICAgICAgdGVzdDoge30sXG4gICAgICAgIHRlc3ROOiAxMjMsXG4gICAgICAgIHRlc3RzOiAnc3RyaW5nJyxcbiAgICAgICAgdGVzdE9iajoge1xuICAgICAgICAgIHRzdDogMTIzLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=