UNPKG

electron-compile

Version:

Electron supporting package to compile JS and CSS in Electron applications

725 lines (575 loc) 85 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _mimeTypes = require('@paulcbetts/mime-types'); var _mimeTypes2 = _interopRequireDefault(_mimeTypes); var _fs = require('fs'); var _fs2 = _interopRequireDefault(_fs); var _zlib = require('zlib'); var _zlib2 = _interopRequireDefault(_zlib); var _path = require('path'); var _path2 = _interopRequireDefault(_path); var _promise = require('./promise'); var _forAllFiles = require('./for-all-files'); var _compileCache = require('./compile-cache'); var _compileCache2 = _interopRequireDefault(_compileCache); var _fileChangeCache = require('./file-change-cache'); var _fileChangeCache2 = _interopRequireDefault(_fileChangeCache); var _readOnlyCompiler = require('./read-only-compiler'); var _readOnlyCompiler2 = _interopRequireDefault(_readOnlyCompiler); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } const d = require('debug-electron')('electron-compile:compiler-host'); require('./rig-mime-types').init(); // This isn't even my const finalForms = { 'text/javascript': true, 'application/javascript': true, 'text/html': true, 'text/css': true, 'image/svg+xml': true, 'application/json': true }; /** * This class is the top-level class that encapsulates all of the logic of * compiling and caching application code. If you're looking for a "Main class", * this is it. * * This class can be created directly but it is usually created via the methods * in config-parser, which will among other things, set up the compiler options * given a project root. * * CompilerHost is also the top-level class that knows how to serialize all of the * information necessary to recreate itself, either as a development host (i.e. * will allow cache misses and actual compilation), or as a read-only version of * itself for production. */ class CompilerHost { /** * Creates an instance of CompilerHost. You probably want to use the methods * in config-parser for development, or {@link createReadonlyFromConfiguration} * for production instead. * * @param {string} rootCacheDir The root directory to use for the cache * * @param {Object} compilers an Object whose keys are input MIME types and * whose values are instances of CompilerBase. Create * this via the {@link createCompilers} method in * config-parser. * * @param {FileChangedCache} fileChangeCache A file-change cache that is * optionally pre-loaded. * * @param {boolean} readOnlyMode If True, cache misses will fail and * compilation will not be attempted. * * @param {CompilerBase} fallbackCompiler (optional) When a file is compiled * which doesn't have a matching compiler, * this compiler will be used instead. If * null, will fail compilation. A good * alternate fallback is the compiler for * 'text/plain', which is guaranteed to be * present. */ constructor(rootCacheDir, compilers, fileChangeCache, readOnlyMode) { let fallbackCompiler = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; let compilersByMimeType = Object.assign({}, compilers); Object.assign(this, { rootCacheDir, compilersByMimeType, fileChangeCache, readOnlyMode, fallbackCompiler }); this.appRoot = this.fileChangeCache.appRoot; this.cachesForCompilers = Object.keys(compilersByMimeType).reduce((acc, x) => { let compiler = compilersByMimeType[x]; if (acc.has(compiler)) return acc; acc.set(compiler, _compileCache2.default.createFromCompiler(rootCacheDir, compiler, fileChangeCache, readOnlyMode)); return acc; }, new Map()); } /** * Creates a production-mode CompilerHost from the previously saved * configuration * * @param {string} rootCacheDir The root directory to use for the cache. This * cache must have cache information saved via * {@link saveConfiguration} * * @param {string} appRoot The top-level directory for your application (i.e. * the one which has your package.json). * * @param {CompilerBase} fallbackCompiler (optional) When a file is compiled * which doesn't have a matching compiler, * this compiler will be used instead. If * null, will fail compilation. A good * alternate fallback is the compiler for * 'text/plain', which is guaranteed to be * present. * * @return {Promise<CompilerHost>} A read-only CompilerHost */ static createReadonlyFromConfiguration(rootCacheDir, appRoot) { let fallbackCompiler = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; return _asyncToGenerator(function* () { let target = _path2.default.join(rootCacheDir, 'compiler-info.json.gz'); let buf = yield _promise.pfs.readFile(target); let info = JSON.parse((yield _promise.pzlib.gunzip(buf))); let fileChangeCache = _fileChangeCache2.default.loadFromData(info.fileChangeCache, appRoot, true); let compilers = Object.keys(info.compilers).reduce(function (acc, x) { let cur = info.compilers[x]; acc[x] = new _readOnlyCompiler2.default(cur.name, cur.compilerVersion, cur.compilerOptions, cur.inputMimeTypes); return acc; }, {}); return new CompilerHost(rootCacheDir, compilers, fileChangeCache, true, fallbackCompiler); })(); } /** * Creates a development-mode CompilerHost from the previously saved * configuration. * * @param {string} rootCacheDir The root directory to use for the cache. This * cache must have cache information saved via * {@link saveConfiguration} * * @param {string} appRoot The top-level directory for your application (i.e. * the one which has your package.json). * * @param {Object} compilersByMimeType an Object whose keys are input MIME * types and whose values are instances * of CompilerBase. Create this via the * {@link createCompilers} method in * config-parser. * * @param {CompilerBase} fallbackCompiler (optional) When a file is compiled * which doesn't have a matching compiler, * this compiler will be used instead. If * null, will fail compilation. A good * alternate fallback is the compiler for * 'text/plain', which is guaranteed to be * present. * * @return {Promise<CompilerHost>} A read-only CompilerHost */ static createFromConfiguration(rootCacheDir, appRoot, compilersByMimeType) { let fallbackCompiler = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; return _asyncToGenerator(function* () { let target = _path2.default.join(rootCacheDir, 'compiler-info.json.gz'); let buf = yield _promise.pfs.readFile(target); let info = JSON.parse((yield _promise.pzlib.gunzip(buf))); let fileChangeCache = _fileChangeCache2.default.loadFromData(info.fileChangeCache, appRoot, false); Object.keys(info.compilers).forEach(function (x) { let cur = info.compilers[x]; compilersByMimeType[x].compilerOptions = cur.compilerOptions; }); return new CompilerHost(rootCacheDir, compilersByMimeType, fileChangeCache, false, fallbackCompiler); })(); } /** * Saves the current compiler configuration to a file that * {@link createReadonlyFromConfiguration} can use to recreate the current * compiler environment * * @return {Promise} Completion */ saveConfiguration() { var _this = this; return _asyncToGenerator(function* () { let serializedCompilerOpts = Object.keys(_this.compilersByMimeType).reduce(function (acc, x) { let compiler = _this.compilersByMimeType[x]; let Klass = Object.getPrototypeOf(compiler).constructor; let val = { name: Klass.name, inputMimeTypes: Klass.getInputMimeTypes(), compilerOptions: compiler.compilerOptions, compilerVersion: compiler.getCompilerVersion() }; acc[x] = val; return acc; }, {}); let info = { fileChangeCache: _this.fileChangeCache.getSavedData(), compilers: serializedCompilerOpts }; let target = _path2.default.join(_this.rootCacheDir, 'compiler-info.json.gz'); let buf = yield _promise.pzlib.gzip(new Buffer(JSON.stringify(info))); yield _promise.pfs.writeFile(target, buf); })(); } /** * Compiles a file and returns the compiled result. * * @param {string} filePath The path to the file to compile * * @return {Promise<object>} An Object with the compiled result * * @property {Object} hashInfo The hash information returned from getHashForPath * @property {string} code The source code if the file was a text file * @property {Buffer} binaryData The file if it was a binary file * @property {string} mimeType The MIME type saved in the cache. * @property {string[]} dependentFiles The dependent files returned from * compiling the file, if any. */ compile(filePath) { return this.readOnlyMode ? this.compileReadOnly(filePath) : this.fullCompile(filePath); } /** * Handles compilation in read-only mode * * @private */ compileReadOnly(filePath) { var _this2 = this; return _asyncToGenerator(function* () { // We guarantee that node_modules are always shipped directly let type = _mimeTypes2.default.lookup(filePath); if (_fileChangeCache2.default.isInNodeModules(filePath)) { return { mimeType: type || 'application/javascript', code: yield _promise.pfs.readFile(filePath, 'utf8') }; } let hashInfo = yield _this2.fileChangeCache.getHashForPath(filePath); // NB: Here, we're basically only using the compiler here to find // the appropriate CompileCache let compiler = CompilerHost.shouldPassthrough(hashInfo) ? _this2.getPassthroughCompiler() : _this2.compilersByMimeType[type || '__lolnothere']; if (!compiler) { compiler = _this2.fallbackCompiler; var _ref = yield compiler.get(filePath); let code = _ref.code; let binaryData = _ref.binaryData; let mimeType = _ref.mimeType; return { code: code || binaryData, mimeType }; } let cache = _this2.cachesForCompilers.get(compiler); var _ref2 = yield cache.get(filePath); let code = _ref2.code; let binaryData = _ref2.binaryData; let mimeType = _ref2.mimeType; code = code || binaryData; if (!code || !mimeType) { throw new Error(`Asked to compile ${ filePath } in production, is this file not precompiled?`); } return { code, mimeType }; })(); } /** * Handles compilation in read-write mode * * @private */ fullCompile(filePath) { var _this3 = this; return _asyncToGenerator(function* () { d(`Compiling ${ filePath }`); let hashInfo = yield _this3.fileChangeCache.getHashForPath(filePath); let type = _mimeTypes2.default.lookup(filePath); if (hashInfo.isInNodeModules) { let code = hashInfo.sourceCode || (yield _promise.pfs.readFile(filePath, 'utf8')); code = yield CompilerHost.fixNodeModulesSourceMapping(code, filePath, _this3.fileChangeCache.appRoot); return { code, mimeType: type }; } let compiler = CompilerHost.shouldPassthrough(hashInfo) ? _this3.getPassthroughCompiler() : _this3.compilersByMimeType[type || '__lolnothere']; if (!compiler) { d(`Falling back to passthrough compiler for ${ filePath }`); compiler = _this3.fallbackCompiler; } if (!compiler) { throw new Error(`Couldn't find a compiler for ${ filePath }`); } let cache = _this3.cachesForCompilers.get(compiler); return yield cache.getOrFetch(filePath, function (filePath, hashInfo) { return _this3.compileUncached(filePath, hashInfo, compiler); }); })(); } /** * Handles invoking compilers independent of caching * * @private */ compileUncached(filePath, hashInfo, compiler) { var _this4 = this; return _asyncToGenerator(function* () { let inputMimeType = _mimeTypes2.default.lookup(filePath); if (hashInfo.isFileBinary) { return { binaryData: hashInfo.binaryData || (yield _promise.pfs.readFile(filePath)), mimeType: inputMimeType, dependentFiles: [] }; } let ctx = {}; let code = hashInfo.sourceCode || (yield _promise.pfs.readFile(filePath, 'utf8')); if (!(yield compiler.shouldCompileFile(code, ctx))) { d(`Compiler returned false for shouldCompileFile: ${ filePath }`); return { code, mimeType: _mimeTypes2.default.lookup(filePath), dependentFiles: [] }; } let dependentFiles = yield compiler.determineDependentFiles(code, filePath, ctx); d(`Using compiler options: ${ JSON.stringify(compiler.compilerOptions) }`); let result = yield compiler.compile(code, filePath, ctx); let shouldInlineHtmlify = inputMimeType !== 'text/html' && result.mimeType === 'text/html'; let isPassthrough = result.mimeType === 'text/plain' || !result.mimeType || CompilerHost.shouldPassthrough(hashInfo); if (finalForms[result.mimeType] && !shouldInlineHtmlify || isPassthrough) { // Got something we can use in-browser, let's return it return Object.assign(result, { dependentFiles }); } else { d(`Recursively compiling result of ${ filePath } with non-final MIME type ${ result.mimeType }, input was ${ inputMimeType }`); hashInfo = Object.assign({ sourceCode: result.code, mimeType: result.mimeType }, hashInfo); compiler = _this4.compilersByMimeType[result.mimeType || '__lolnothere']; if (!compiler) { d(`Recursive compile failed - intermediate result: ${ JSON.stringify(result) }`); throw new Error(`Compiling ${ filePath } resulted in a MIME type of ${ result.mimeType }, which we don't know how to handle`); } return yield _this4.compileUncached(`${ filePath }.${ _mimeTypes2.default.extension(result.mimeType || 'txt') }`, hashInfo, compiler); } })(); } /** * Pre-caches an entire directory of files recursively. Usually used for * building custom compiler tooling. * * @param {string} rootDirectory The top-level directory to compile * * @param {Function} shouldCompile (optional) A Function which allows the * caller to disable compiling certain files. * It takes a fully-qualified path to a file, * and should return a Boolean. * * @return {Promise} Completion. */ compileAll(rootDirectory) { var _this5 = this; let shouldCompile = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; return _asyncToGenerator(function* () { let should = shouldCompile || function () { return true; }; yield (0, _forAllFiles.forAllFiles)(rootDirectory, function (f) { if (!should(f)) return; d(`Compiling ${ f }`); return _this5.compile(f, _this5.compilersByMimeType); }); })(); } /* * Sync Methods */ compileSync(filePath) { return this.readOnlyMode ? this.compileReadOnlySync(filePath) : this.fullCompileSync(filePath); } static createReadonlyFromConfigurationSync(rootCacheDir, appRoot) { let fallbackCompiler = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; let target = _path2.default.join(rootCacheDir, 'compiler-info.json.gz'); let buf = _fs2.default.readFileSync(target); let info = JSON.parse(_zlib2.default.gunzipSync(buf)); let fileChangeCache = _fileChangeCache2.default.loadFromData(info.fileChangeCache, appRoot, true); let compilers = Object.keys(info.compilers).reduce((acc, x) => { let cur = info.compilers[x]; acc[x] = new _readOnlyCompiler2.default(cur.name, cur.compilerVersion, cur.compilerOptions, cur.inputMimeTypes); return acc; }, {}); return new CompilerHost(rootCacheDir, compilers, fileChangeCache, true, fallbackCompiler); } static createFromConfigurationSync(rootCacheDir, appRoot, compilersByMimeType) { let fallbackCompiler = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; let target = _path2.default.join(rootCacheDir, 'compiler-info.json.gz'); let buf = _fs2.default.readFileSync(target); let info = JSON.parse(_zlib2.default.gunzipSync(buf)); let fileChangeCache = _fileChangeCache2.default.loadFromData(info.fileChangeCache, appRoot, false); Object.keys(info.compilers).forEach(x => { let cur = info.compilers[x]; compilersByMimeType[x].compilerOptions = cur.compilerOptions; }); return new CompilerHost(rootCacheDir, compilersByMimeType, fileChangeCache, false, fallbackCompiler); } saveConfigurationSync() { let serializedCompilerOpts = Object.keys(this.compilersByMimeType).reduce((acc, x) => { let compiler = this.compilersByMimeType[x]; let Klass = Object.getPrototypeOf(compiler).constructor; let val = { name: Klass.name, inputMimeTypes: Klass.getInputMimeTypes(), compilerOptions: compiler.compilerOptions, compilerVersion: compiler.getCompilerVersion() }; acc[x] = val; return acc; }, {}); let info = { fileChangeCache: this.fileChangeCache.getSavedData(), compilers: serializedCompilerOpts }; let target = _path2.default.join(this.rootCacheDir, 'compiler-info.json.gz'); let buf = _zlib2.default.gzipSync(new Buffer(JSON.stringify(info))); _fs2.default.writeFileSync(target, buf); } compileReadOnlySync(filePath) { // We guarantee that node_modules are always shipped directly let type = _mimeTypes2.default.lookup(filePath); if (_fileChangeCache2.default.isInNodeModules(filePath)) { return { mimeType: type || 'application/javascript', code: _fs2.default.readFileSync(filePath, 'utf8') }; } let hashInfo = this.fileChangeCache.getHashForPathSync(filePath); // We guarantee that node_modules are always shipped directly if (hashInfo.isInNodeModules) { return { mimeType: type, code: hashInfo.sourceCode || _fs2.default.readFileSync(filePath, 'utf8') }; } // NB: Here, we're basically only using the compiler here to find // the appropriate CompileCache let compiler = CompilerHost.shouldPassthrough(hashInfo) ? this.getPassthroughCompiler() : this.compilersByMimeType[type || '__lolnothere']; if (!compiler) { compiler = this.fallbackCompiler; var _compiler$getSync = compiler.getSync(filePath); let code = _compiler$getSync.code; let binaryData = _compiler$getSync.binaryData; let mimeType = _compiler$getSync.mimeType; return { code: code || binaryData, mimeType }; } let cache = this.cachesForCompilers.get(compiler); var _cache$getSync = cache.getSync(filePath); let code = _cache$getSync.code; let binaryData = _cache$getSync.binaryData; let mimeType = _cache$getSync.mimeType; code = code || binaryData; if (!code || !mimeType) { throw new Error(`Asked to compile ${ filePath } in production, is this file not precompiled?`); } return { code, mimeType }; } fullCompileSync(filePath) { d(`Compiling ${ filePath }`); let hashInfo = this.fileChangeCache.getHashForPathSync(filePath); let type = _mimeTypes2.default.lookup(filePath); if (hashInfo.isInNodeModules) { let code = hashInfo.sourceCode || _fs2.default.readFileSync(filePath, 'utf8'); code = CompilerHost.fixNodeModulesSourceMappingSync(code, filePath, this.fileChangeCache.appRoot); return { code, mimeType: type }; } let compiler = CompilerHost.shouldPassthrough(hashInfo) ? this.getPassthroughCompiler() : this.compilersByMimeType[type || '__lolnothere']; if (!compiler) { d(`Falling back to passthrough compiler for ${ filePath }`); compiler = this.fallbackCompiler; } if (!compiler) { throw new Error(`Couldn't find a compiler for ${ filePath }`); } let cache = this.cachesForCompilers.get(compiler); return cache.getOrFetchSync(filePath, (filePath, hashInfo) => this.compileUncachedSync(filePath, hashInfo, compiler)); } compileUncachedSync(filePath, hashInfo, compiler) { let inputMimeType = _mimeTypes2.default.lookup(filePath); if (hashInfo.isFileBinary) { return { binaryData: hashInfo.binaryData || _fs2.default.readFileSync(filePath), mimeType: inputMimeType, dependentFiles: [] }; } let ctx = {}; let code = hashInfo.sourceCode || _fs2.default.readFileSync(filePath, 'utf8'); if (!compiler.shouldCompileFileSync(code, ctx)) { d(`Compiler returned false for shouldCompileFile: ${ filePath }`); return { code, mimeType: _mimeTypes2.default.lookup(filePath), dependentFiles: [] }; } let dependentFiles = compiler.determineDependentFilesSync(code, filePath, ctx); let result = compiler.compileSync(code, filePath, ctx); let shouldInlineHtmlify = inputMimeType !== 'text/html' && result.mimeType === 'text/html'; let isPassthrough = result.mimeType === 'text/plain' || !result.mimeType || CompilerHost.shouldPassthrough(hashInfo); if (finalForms[result.mimeType] && !shouldInlineHtmlify || isPassthrough) { // Got something we can use in-browser, let's return it return Object.assign(result, { dependentFiles }); } else { d(`Recursively compiling result of ${ filePath } with non-final MIME type ${ result.mimeType }, input was ${ inputMimeType }`); hashInfo = Object.assign({ sourceCode: result.code, mimeType: result.mimeType }, hashInfo); compiler = this.compilersByMimeType[result.mimeType || '__lolnothere']; if (!compiler) { d(`Recursive compile failed - intermediate result: ${ JSON.stringify(result) }`); throw new Error(`Compiling ${ filePath } resulted in a MIME type of ${ result.mimeType }, which we don't know how to handle`); } return this.compileUncachedSync(`${ filePath }.${ _mimeTypes2.default.extension(result.mimeType || 'txt') }`, hashInfo, compiler); } } compileAllSync(rootDirectory) { let shouldCompile = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; let should = shouldCompile || function () { return true; }; (0, _forAllFiles.forAllFilesSync)(rootDirectory, f => { if (!should(f)) return; return this.compileSync(f, this.compilersByMimeType); }); } /* * Other stuff */ /** * Returns the passthrough compiler * * @private */ getPassthroughCompiler() { return this.compilersByMimeType['text/plain']; } /** * Determines whether we should even try to compile the content. Note that in * some cases, content will still be in cache even if this returns true, and * in other cases (isInNodeModules), we'll know explicitly to not even bother * looking in the cache. * * @private */ static shouldPassthrough(hashInfo) { return hashInfo.isMinified || hashInfo.isInNodeModules || hashInfo.hasSourceMap || hashInfo.isFileBinary; } /** * Look at the code of a node modules and see the sourceMapping path. * If there is any, check the path and try to fix it with and * root relative path. * @private */ static fixNodeModulesSourceMapping(sourceCode, sourcePath, appRoot) { return _asyncToGenerator(function* () { let regexSourceMapping = /\/\/#.*sourceMappingURL=(?!data:)([^"'].*)/i; let sourceMappingCheck = sourceCode.match(regexSourceMapping); if (sourceMappingCheck && sourceMappingCheck[1] && sourceMappingCheck[1] !== '') { let sourceMapPath = sourceMappingCheck[1]; try { yield _promise.pfs.stat(sourceMapPath); } catch (error) { let normRoot = _path2.default.normalize(appRoot); let absPathToModule = _path2.default.dirname(sourcePath.replace(normRoot, '').substring(1)); let newMapPath = _path2.default.join(absPathToModule, sourceMapPath); return sourceCode.replace(regexSourceMapping, `//# sourceMappingURL=${ newMapPath }`); } } return sourceCode; })(); } /** * Look at the code of a node modules and see the sourceMapping path. * If there is any, check the path and try to fix it with and * root relative path. * @private */ static fixNodeModulesSourceMappingSync(sourceCode, sourcePath, appRoot) { let regexSourceMapping = /\/\/#.*sourceMappingURL=(?!data:)([^"'].*)/i; let sourceMappingCheck = sourceCode.match(regexSourceMapping); if (sourceMappingCheck && sourceMappingCheck[1] && sourceMappingCheck[1] !== '') { let sourceMapPath = sourceMappingCheck[1]; try { _fs2.default.statSync(sourceMapPath); } catch (error) { let normRoot = _path2.default.normalize(appRoot); let absPathToModule = _path2.default.dirname(sourcePath.replace(normRoot, '').substring(1)); let newMapPath = _path2.default.join(absPathToModule, sourceMapPath); return sourceCode.replace(regexSourceMapping, `//# sourceMappingURL=${ newMapPath }`); } } return sourceCode; } } exports.default = CompilerHost; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9jb21waWxlci1ob3N0LmpzIl0sIm5hbWVzIjpbImQiLCJyZXF1aXJlIiwiaW5pdCIsImZpbmFsRm9ybXMiLCJDb21waWxlckhvc3QiLCJjb25zdHJ1Y3RvciIsInJvb3RDYWNoZURpciIsImNvbXBpbGVycyIsImZpbGVDaGFuZ2VDYWNoZSIsInJlYWRPbmx5TW9kZSIsImZhbGxiYWNrQ29tcGlsZXIiLCJjb21waWxlcnNCeU1pbWVUeXBlIiwiT2JqZWN0IiwiYXNzaWduIiwiYXBwUm9vdCIsImNhY2hlc0ZvckNvbXBpbGVycyIsImtleXMiLCJyZWR1Y2UiLCJhY2MiLCJ4IiwiY29tcGlsZXIiLCJoYXMiLCJzZXQiLCJjcmVhdGVGcm9tQ29tcGlsZXIiLCJNYXAiLCJjcmVhdGVSZWFkb25seUZyb21Db25maWd1cmF0aW9uIiwidGFyZ2V0Iiwiam9pbiIsImJ1ZiIsInJlYWRGaWxlIiwiaW5mbyIsIkpTT04iLCJwYXJzZSIsImd1bnppcCIsImxvYWRGcm9tRGF0YSIsImN1ciIsIm5hbWUiLCJjb21waWxlclZlcnNpb24iLCJjb21waWxlck9wdGlvbnMiLCJpbnB1dE1pbWVUeXBlcyIsImNyZWF0ZUZyb21Db25maWd1cmF0aW9uIiwiZm9yRWFjaCIsInNhdmVDb25maWd1cmF0aW9uIiwic2VyaWFsaXplZENvbXBpbGVyT3B0cyIsIktsYXNzIiwiZ2V0UHJvdG90eXBlT2YiLCJ2YWwiLCJnZXRJbnB1dE1pbWVUeXBlcyIsImdldENvbXBpbGVyVmVyc2lvbiIsImdldFNhdmVkRGF0YSIsImd6aXAiLCJCdWZmZXIiLCJzdHJpbmdpZnkiLCJ3cml0ZUZpbGUiLCJjb21waWxlIiwiZmlsZVBhdGgiLCJjb21waWxlUmVhZE9ubHkiLCJmdWxsQ29tcGlsZSIsInR5cGUiLCJsb29rdXAiLCJpc0luTm9kZU1vZHVsZXMiLCJtaW1lVHlwZSIsImNvZGUiLCJoYXNoSW5mbyIsImdldEhhc2hGb3JQYXRoIiwic2hvdWxkUGFzc3Rocm91Z2giLCJnZXRQYXNzdGhyb3VnaENvbXBpbGVyIiwiZ2V0IiwiYmluYXJ5RGF0YSIsImNhY2hlIiwiRXJyb3IiLCJzb3VyY2VDb2RlIiwiZml4Tm9kZU1vZHVsZXNTb3VyY2VNYXBwaW5nIiwiZ2V0T3JGZXRjaCIsImNvbXBpbGVVbmNhY2hlZCIsImlucHV0TWltZVR5cGUiLCJpc0ZpbGVCaW5hcnkiLCJkZXBlbmRlbnRGaWxlcyIsImN0eCIsInNob3VsZENvbXBpbGVGaWxlIiwiZGV0ZXJtaW5lRGVwZW5kZW50RmlsZXMiLCJyZXN1bHQiLCJzaG91bGRJbmxpbmVIdG1saWZ5IiwiaXNQYXNzdGhyb3VnaCIsImV4dGVuc2lvbiIsImNvbXBpbGVBbGwiLCJyb290RGlyZWN0b3J5Iiwic2hvdWxkQ29tcGlsZSIsInNob3VsZCIsImYiLCJjb21waWxlU3luYyIsImNvbXBpbGVSZWFkT25seVN5bmMiLCJmdWxsQ29tcGlsZVN5bmMiLCJjcmVhdGVSZWFkb25seUZyb21Db25maWd1cmF0aW9uU3luYyIsInJlYWRGaWxlU3luYyIsImd1bnppcFN5bmMiLCJjcmVhdGVGcm9tQ29uZmlndXJhdGlvblN5bmMiLCJzYXZlQ29uZmlndXJhdGlvblN5bmMiLCJnemlwU3luYyIsIndyaXRlRmlsZVN5bmMiLCJnZXRIYXNoRm9yUGF0aFN5bmMiLCJnZXRTeW5jIiwiZml4Tm9kZU1vZHVsZXNTb3VyY2VNYXBwaW5nU3luYyIsImdldE9yRmV0Y2hTeW5jIiwiY29tcGlsZVVuY2FjaGVkU3luYyIsInNob3VsZENvbXBpbGVGaWxlU3luYyIsImRldGVybWluZURlcGVuZGVudEZpbGVzU3luYyIsImNvbXBpbGVBbGxTeW5jIiwiaXNNaW5pZmllZCIsImhhc1NvdXJjZU1hcCIsInNvdXJjZVBhdGgiLCJyZWdleFNvdXJjZU1hcHBpbmciLCJzb3VyY2VNYXBwaW5nQ2hlY2siLCJtYXRjaCIsInNvdXJjZU1hcFBhdGgiLCJzdGF0IiwiZXJyb3IiLCJub3JtUm9vdCIsIm5vcm1hbGl6ZSIsImFic1BhdGhUb01vZHVsZSIsImRpcm5hbWUiLCJyZXBsYWNlIiwi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