UNPKG

template-kit

Version:
785 lines (636 loc) 84.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.TemplateEngine = void 0; var _ejs = _interopRequireDefault(require("ejs")); var _fsExtra = _interopRequireDefault(require("fs-extra")); var _globalModules = _interopRequireDefault(require("global-modules")); var _hookEmitter = _interopRequireDefault(require("hook-emitter")); var _hostedGitInfo = _interopRequireDefault(require("hosted-git-info")); var _inly = _interopRequireDefault(require("inly")); var _pacote = _interopRequireDefault(require("pacote")); var _path = _interopRequireDefault(require("path")); var _snooplogg = _interopRequireDefault(require("snooplogg")); var _tmp = _interopRequireDefault(require("tmp")); var _validateNpmPackageName = _interopRequireDefault(require("validate-npm-package-name")); var request = _interopRequireWildcard(require("@axway/amplify-request")); var _appcdPath = require("appcd-path"); var _globGitignore = require("glob-gitignore"); var _isbinaryfile = require("isbinaryfile"); var _appcdFs = require("appcd-fs"); var _util = require("util"); var _appcdSubprocess = require("appcd-subprocess"); function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } /* istanbul ignore if */ if (!Error.prepareStackTrace) { require('source-map-support/register'); } const { error, log, warn } = (0, _snooplogg.default)('template-kit'); const { highlight } = _snooplogg.default.styles; const archiveRegExp = /[^\\/]+(\.zip|\.tgz|\.tbz2|\.tar\.gz|\.tar\.bz2|(?<!\.tar)\.gz|(?<!\.tar)\.bz2)$/; const dotIgnoreRegExp = /(?<!\w)(?<!\.)(gitignore|npmignore)$/; const fileRegExp = /\{\{(\w+?)\}\}/g; class TemplateEngine extends _hookEmitter.default { /** * The list of default `multimatch` patterns. * * @type {Array.<String>} * @access public */ /** * Initializes the template engine options. * * @param {Object} [opts] - Various options. * @param {Object} [opts.requestOptions] - Options to pass into the `got` HTTP client. * Supported properties are `caFile`, `certFile`, `keyFile`, `proxy`, and `strictSSL`. * @access public */ constructor(opts = {}) { if (opts && typeof opts !== 'object') { throw new TypeError('Expected options to be an object'); } super(); this.requestOptions = (opts === null || opts === void 0 ? void 0 : opts.requestOptions) || {}; } /** * Builds a project based on the specified template and options. * * @param {Object} opts - Various options. * @param {Object} [opts.data] - A data object that is passed into `ejs` when copying template * files. * @param {String} opts.dest - The destination directory to create the project in. * @param {Set|Array.<String>} [opts.filters] - A list of file patterns to pass into * `micromatch` when copying files. * @param {Boolean} [opts.force] - When `true`, overrides the destination if it already exists. * @param {Boolean} [opts.git=true] - When `true` and `git` executable is found, after the * the project is generated, initialize a git repo in the project directory. * @param {Array.<String>} [opts.npmArgs] - An array of additional parameters to pass into npm. * Useful if you need to add extra arguments for things such as skipping shrinkwrap. * @param {String} opts.src - The path to a directory, archive file, globally installed npm * package, archive URL, npm package name, or git repo. * @returns {Promise} * @access public */ async run(opts) { if (!opts || typeof opts !== 'object') { throw new TypeError('Expected options to be an object'); } const state = await this.hook('init', this, this.init)(opts); try { if (state.gitInfo = _hostedGitInfo.default.fromUrl(state.src)) { await this.gitClone(state); } else if (/^https?:\/\//.test(state.src)) { await this.download(state); } // if the source is a file, then it's an archive and it must be extracted if ((0, _appcdFs.isFile)(state.src)) { await this.extract(state); } if ((0, _appcdFs.isDir)(state.src)) {// pre-existing local directory or result of git clone, file download, or extracted // archive } else { const globalDir = process.env.GLOBAL_NPM_MODULES_DIR || _globalModules.default; let globalPackageDir; for (const name of _fsExtra.default.readdirSync(globalDir)) { const pkg = await this.loadPackage(_path.default.join(globalDir, name)); if (pkg && pkg.name === state.src) { globalPackageDir = _path.default.join(globalDir, name); state.pkg = pkg; break; } } if (globalPackageDir) { // global npm package log(`Found global npm package: ${highlight(globalPackageDir)}`); state.src = globalPackageDir; } else { // remote npm package try { const result = (0, _validateNpmPackageName.default)(state.src.split('@')[0]); if (!result.validForNewPackages && !result.validForOldPackages) { throw new Error('Definitely not a valid npm package name'); } state.npmManifest = await _pacote.default.manifest(state.src, request.options({ defaults: this.requestOptions, fullMetadata: true })); } catch (e) { throw new Error('Unable to determine template source'); } await this.npmDownload(state); } } // load the package.json, if exists if (state.pkg === undefined) { state.pkg = await this.loadPackage(state.src); } // try to determine meta file let metaFile = state.pkg && state.pkg.main && _path.default.resolve(state.src, state.pkg.main); if ((0, _appcdFs.isFile)(metaFile) || (0, _appcdFs.isFile)(metaFile = _path.default.join(state.src, 'meta.js'))) { state.metaFile = metaFile; state.filters.add(`!${_path.default.relative(state.src, metaFile)}`); } await this.loadMeta(state); /* istanbul ignore else */ if (state.template) { state.src = _path.default.resolve(state.src, state.template); } await this.hook('create', async state => { await this.copy(state); await this.npmInstall(state); await this.gitInit(state); })(state); if (typeof state.complete === 'function') { await state.complete(state); } } finally { await this.hook('cleanup', async state => { for (const file of state.disposables) { /* istanbul ignore else */ if (file.startsWith(_tmp.default.tmpdir)) { try { await _fsExtra.default.remove(file); } catch (e) { /* istanbul ignore next */ warn(`Unable to remove temp file: ${highlight(file)}`); } } } })(state); } } /** * Copy files from the state source to the destination. * * @param {Object} state - The run state. * @returns {Promise} * @access private */ async copy(state) { await this.hook('copy', async state => { const copyFile = (0, _util.promisify)(_fsExtra.default.copyFile); const readFile = (0, _util.promisify)(_fsExtra.default.readFile); const writeFile = (0, _util.promisify)(_fsExtra.default.writeFile); // separate positive from negative paths let patterns = []; const ignore = []; for (const pattern of Array.from(state.filters)) { if (pattern[0] === '!') { ignore.push(pattern.substring(1)); } else { patterns.push(pattern); } } if (!patterns.length) { patterns = ['**']; } log('Building template file list...'); log(patterns); // if there's no patterns, then match everything const files = await (0, _globGitignore.glob)(patterns, { cwd: state.src, dot: true, ignore }); await _fsExtra.default.mkdirs(state.dest); for (const file of files) { const destFilename = this.renderFilename(file, state.data).replace(dotIgnoreRegExp, '.$1'); state.srcFile = _path.default.join(state.src, file); state.destFile = _path.default.join(state.dest, destFilename); if ((0, _appcdFs.isDir)(state.srcFile)) { log(`Creating directory ${highlight(state.destFile)}`); await _fsExtra.default.mkdirs(state.destFile); continue; } await this.hook('copy-file', async state => { if (await (0, _isbinaryfile.isBinaryFile)(state.srcFile)) { // copy log(`Copying ${highlight(state.srcFile)} => ${highlight(_path.default.relative(state.srcFile, state.destFile))}`); await copyFile(state.srcFile, state.destFile); } else { // render log(`Copying ${highlight(state.srcFile)} => ${highlight(_path.default.relative(state.srcFile, state.destFile))}`); let contents = await readFile(state.srcFile); contents = await _ejs.default.render(contents.toString(), state.data, { async: true, root: state.src }); await writeFile(state.destFile, contents); } })(state); } delete state.srcFile; delete state.destFile; })(state); } /** * Download a file to a temp directory. * * @param {Object} state - The run state. * @returns {Promise} * @access private */ async download(state) { await this.hook('download', async state => { return new Promise((resolve, reject) => { log(`Downloading ${highlight(state.src)}`); const got = request.init({ defaults: this.requestOptions }); const stream = got.stream(state.src).on('response', response => { const { headers } = response; const length = headers['content-length']; const type = headers['content-type']; let filename; let m; log(headers); // try to determine the file extension by the content disposition filename // this is likely the most trustworthy option /* istanbul ignore else */ if (!filename) { const cd = headers['content-disposition']; m = cd && cd.match(/filename[^;=\n]*=['"]*(.*?\2|[^'";\n]*)/); filename = m && m[1]; } // try to determine the file extension by the filename in the url if (!filename && (m = state.src.match(archiveRegExp))) { filename = m[0]; } // try to determine the file extension by content type // sadly, .zip is pretty much the only extension we can reliably trust // the remaining supported archive types are too ambiguous if (!filename && (type === 'application/zip' || type === 'application/x-zip-compressed')) { filename = `temp-template-${Date.now()}.zip`; } if (!filename) { // we don't know what the filename is, so there's no way to know what the // file type is return reject(new Error('Unable to determine source file type')); } state.src = _path.default.join(this.makeTemp(state), filename); log(`Writing file to ${highlight(state.src)} (${length || '?'} bytes)`); const out = _fsExtra.default.createWriteStream(state.src); out.on('error', reject); out.on('close', () => { log(`Wrote ${_fsExtra.default.statSync(state.src).size} bytes`); resolve(state.src); }); stream.pipe(out); }).on('error', reject); }); })(state); } /** * Extract an archive to a temp directory. * * @param {Object} state - The run state. * @returns {Promise} * @access private */ async extract(state) { state.extractDest = this.makeTemp(state); await this.hook('extract', async state => { return new Promise((resolve, reject) => { log(`Extracting ${highlight(state.src)} => ${highlight(_path.default.relative(_path.default.dirname(state.src), state.extractDest))}`); (0, _inly.default)(state.src, state.extractDest).on('file', file => this.emit('extract-file', state, file)).on('progress', percent => this.emit('extract-progress', state, percent)).on('end', () => resolve(state.src = state.extractDest)).on('error', reject); }); })(state); } /** * Clones a git repo to a temp directory. * * @param {Object} state - The run state. * @returns {Promise} * @access private */ async gitClone(state) { const dir = this.makeTemp(state); const { gitInfo } = state; const branch = gitInfo.committish; const cmd = await this.git(); const args = ['clone', '--depth=1']; if (!cmd) { throw new Error('Unable to find "git" executable'); } if (branch) { args.push('--branch', branch); } if (gitInfo.getDefaultRepresentation() === 'sshurl') { args.push(gitInfo.ssh({ noCommittish: true })); } else { args.push(gitInfo.https({ noCommittish: true, noGitPlus: true })); } try { state.src = await this.hook('git-clone', async (state, args, opts) => { log(`Cloning repo into ${highlight(opts.cwd)}`); await (0, _appcdSubprocess.run)(cmd, args, opts); return _path.default.join(dir, gitInfo.project); })(state, args, { cwd: dir }); } catch (e) { const m = e.stderr.match(/^ERROR:\s*(.+)\.?$/m); e.stderr.trim().split(/\r?\n/).forEach(line => error(line)); throw m ? new Error(m[1]) : /* istanbul ignore next */ e; } } /** * Attempts to locate the git executable. * * @returns {Promise.<String>} Resolves the path to the git executable. * @access private */ async git() { try { return await (0, _appcdSubprocess.which)('git'); } catch (e) {// squelch } } /** * Initializes a git repo in the destination directory. * * @param {Object} state - The run state. * @returns {Promise} * @access private */ async gitInit(state) { const cmd = await this.git(); if (cmd && state.git !== false) { await this.hook('git-init', async (state, args, opts) => { log(`Initializing git repo in ${highlight(opts.cwd)}`); await (0, _appcdSubprocess.run)(cmd, args, opts); })(state, ['init'], { cwd: state.dest }); } else { warn('git executable not found, skipping git init'); } } /** * Initializes the state prior running. * * @param {Object} opts - Various options. * @returns {Object} * @access private */ init(opts) { if (!opts || typeof opts !== 'object') { throw new TypeError('Expected options to be an object'); } const state = { template: '.', ...opts, disposables: [], extractDest: undefined, gitInfo: undefined, meta: {}, metaFile: undefined, npmManifest: undefined, pkg: undefined, prompts: {} }; if (!state.src || typeof state.src !== 'string') { throw new TypeError('Expected source to be a path, npm package name, URL, or git repo'); } if (!state.dest || typeof state.dest !== 'string') { throw new TypeError('Expected destination to be a path'); } state.dest = (0, _appcdPath.expandPath)(state.dest); let stat; try { stat = _fsExtra.default.statSync(state.dest); } catch (e) {// does not exist, continue } // if file exists and not a dir or is a non-empty dir if (stat && !state.force && (!stat.isDirectory() || _fsExtra.default.readdirSync(state.dest).length)) { throw new Error('Destination already exists'); } /* istanbul ignore else */ if (!state.data) { state.data = {}; } else if (typeof state.data !== 'object') { throw new TypeError('Expected data to be an object'); } if (!state.filters) { state.filters = new Set(TemplateEngine.DefaultFilters); } else if (Array.isArray(state.filters) || state.filters instanceof Set) { state.filters = new Set([...state.filters]); } else { throw new TypeError('Expected filters to be an array or set of file patterns'); } return state; } /** * Loads and validates the template's metadata. * * @param {Object} state - The run state. * @returns {Promise} * @access private */ async loadMeta(state) { // load the template meta const meta = await this.hook('load-meta', async state => { let meta; if (state.metaFile) { log(`Loading metadata: ${highlight(state.metaFile)}`); meta = require(state.metaFile); } // if this is an ES6 module, grab the default export if (meta && typeof meta === 'object' && meta.__esModule) { meta = meta.default; } return (typeof meta === 'function' ? await meta(state) : meta) || {}; })(state); if (typeof meta !== 'object') { throw new TypeError('Expected template meta export to be an object or function'); } if (meta.complete) { if (typeof meta.complete !== 'function') { throw new TypeError('Expected template meta complete callback to be a function'); } state.complete = meta.complete; } if (meta.data) { if (typeof meta.data !== 'object') { throw new TypeError('Expected template meta data to be an object'); } state.data = { ...meta.data, ...state.data }; } if (meta.filters) { if (!Array.isArray(meta.filters) && !(meta.filters instanceof Set)) { throw new TypeError('Expected template meta filters to be an array or set of file patterns'); } for (const filter of meta.filters) { let op = filter[0] === '!' ? filter.substring(1) : `!${filter}`; if (state.filters.has(op)) { state.filters.delete(op); } state.filters.add(filter); } } if (meta.template && state.template === '.') { if (typeof meta.template !== 'string') { throw new TypeError('Expected template meta relative template path to be a non-empty string'); } state.template = meta.template; } if (meta.prompts) { if (typeof meta.prompts !== 'object') { throw new TypeError('Expected template meta prompts to be an object'); } const prompts = {}; // validate the prompt descriptors and copy them into a clean object for (const [name, descriptor] of Object.entries(meta.prompts)) { if (!descriptor || typeof descriptor !== 'object') { throw new TypeError(`Expected meta prompt descriptor for "${name}" to be an object`); } prompts[name] = descriptor; } // if we have any prompts, then set the state and emit the `prompt` event if (Object.keys(prompts).length) { state.prompts = prompts; // if there's a template prompt and the template was explicitly set, then override // the default prompt choice if (state.prompts.template && state.template !== '.') { state.prompts.template.default = state.template; } await this.emit('prompt', state); // populate any default values for (const [name, descriptor] of Object.entries(state.prompts)) { if (descriptor.default !== undefined && state.data[name] === undefined) { state.data[name] = descriptor.default; } } } } } /** * Attempt to load the `package.json`, if it exists. * * @param {String} dir - The path of the package to load the `package.json` from. * @returns {Promise<Object>} Resolves the parsed contents or `null`. * @access private */ async loadPackage(dir) { try { return await _fsExtra.default.readJson(_path.default.join(dir, 'package.json')); } catch (e) { return null; } } /** * Creates a temp directory. * * @param {Object} state - The run state. * @returns {String} * @access private */ makeTemp(state) { const { name } = _tmp.default.dirSync({ mode: '755', unsafeCleanup: true }); state.disposables.push(name); return name; } /** * Downloads and extracts an npm package, then manually renames `.gitignore` files to * workaround bug. * * @param {Object} state - The run state. * @returns {Promise} * @access private */ async npmDownload(state) { state.src = this.makeTemp(state); await this.hook('npm-download', async state => { log(`Downloading ${highlight(`${state.npmManifest.name}@${state.npmManifest.version}`)}`); await _pacote.default.extract(`${state.npmManifest.name}@${state.npmManifest.version}`, state.src, request.options({ defaults: this.requestOptions })); })(state); // pacote has a "feature" where .gitignore is renamed to .npmignore and there's nothing we // can do about it (https://github.com/npm/pacote/issues/33) // as a workaround, if we find any files named `gitignore`, rename them to `.gitignore` const walk = dir => { for (let name of _fsExtra.default.readdirSync(dir)) { const file = _path.default.join(dir, name); /* istanbul ignore if */ if ((0, _appcdFs.isDir)(file)) { walk(file); } else if (name === 'gitignore' || name === 'npmignore') { const dest = _path.default.join(dir, `.${name}`); log(`Renaming ${highlight(file)} => ${highlight(_path.default.relative(file, dest))}`); _fsExtra.default.renameSync(file, dest); } } }; walk(state.src); } /** * Installs template npm dependencies if a `package.json` exists. * * @param {Object} state - The run state. * @returns {Promise} * @access private */ async npmInstall(state) { if (!(0, _appcdFs.isFile)(_path.default.join(state.dest, 'package.json'))) { log('Template does not have a package.json, skipping npm install'); return; } const cacheDir = this.makeTemp(state); const args = new Set(['install', '--no-audit', '--no-package-lock', ...(Array.isArray(state.npmArgs) ? /* istanbul ignore next */ state.npmArgs : [])]); const env = { ...process.env, NO_UPDATE_NOTIFIER: 1, npm_config_cache: cacheDir }; let code; try { code = await this.hook('npm-install', async (state, cmd, args, opts) => { log(`Install template dependencies: ${highlight(state.dest)}`); return (await (0, _appcdSubprocess.run)(cmd, args, opts)).code; })(state, await (0, _appcdSubprocess.which)('npm'), Array.from(args), { cwd: state.dest, env }); } finally { (code ? /* istanbul ignore next */ warn : log)(`npm install exited (code ${code})`); } } /** * Replaces variables in a path. * * @param {String} file - A file path that contains the `{{variable}}` tokens. * @param {Object} data - An object with data to populate the filename. * @returns {String} * @access private */ renderFilename(file, data) { if (typeof file !== 'string' || !data) { return file; } return file.replace(fileRegExp, (match, name) => { return Object.prototype.hasOwnProperty.call(data, name) ? String(data[name]) : match; }); } } exports.TemplateEngine = TemplateEngine; _defineProperty(TemplateEngine, "DefaultFilters", ['!.git', '!node_modules']); var _default = TemplateEngine; exports.default = _default; //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbIkVycm9yIiwicHJlcGFyZVN0YWNrVHJhY2UiLCJyZXF1aXJlIiwiZXJyb3IiLCJsb2ciLCJ3YXJuIiwiaGlnaGxpZ2h0Iiwic25vb3Bsb2dnIiwic3R5bGVzIiwiYXJjaGl2ZVJlZ0V4cCIsImRvdElnbm9yZVJlZ0V4cCIsImZpbGVSZWdFeHAiLCJUZW1wbGF0ZUVuZ2luZSIsIkhvb2tFbWl0dGVyIiwiY29uc3RydWN0b3IiLCJvcHRzIiwiVHlwZUVycm9yIiwicmVxdWVzdE9wdGlvbnMiLCJydW4iLCJzdGF0ZSIsImhvb2siLCJpbml0IiwiZ2l0SW5mbyIsImhvc3RlZEdpdEluZm8iLCJmcm9tVXJsIiwic3JjIiwiZ2l0Q2xvbmUiLCJ0ZXN0IiwiZG93bmxvYWQiLCJleHRyYWN0IiwiZ2xvYmFsRGlyIiwicHJvY2VzcyIsImVudiIsIkdMT0JBTF9OUE1fTU9EVUxFU19ESVIiLCJnbG9iYWxNb2R1bGVzIiwiZ2xvYmFsUGFja2FnZURpciIsIm5hbWUiLCJmcyIsInJlYWRkaXJTeW5jIiwicGtnIiwibG9hZFBhY2thZ2UiLCJwYXRoIiwiam9pbiIsInJlc3VsdCIsInNwbGl0IiwidmFsaWRGb3JOZXdQYWNrYWdlcyIsInZhbGlkRm9yT2xkUGFja2FnZXMiLCJucG1NYW5pZmVzdCIsInBhY290ZSIsIm1hbmlmZXN0IiwicmVxdWVzdCIsIm9wdGlvbnMiLCJkZWZhdWx0cyIsImZ1bGxNZXRhZGF0YSIsImUiLCJucG1Eb3dubG9hZCIsInVuZGVmaW5lZCIsIm1ldGFGaWxlIiwibWFpbiIsInJlc29sdmUiLCJmaWx0ZXJzIiwiYWRkIiwicmVsYXRpdmUiLCJsb2FkTWV0YSIsInRlbXBsYXRlIiwiY29weSIsIm5wbUluc3RhbGwiLCJnaXRJbml0IiwiY29tcGxldGUiLCJmaWxlIiwiZGlzcG9zYWJsZXMiLCJzdGFydHNXaXRoIiwidG1wIiwidG1wZGlyIiwicmVtb3ZlIiwiY29weUZpbGUiLCJyZWFkRmlsZSIsIndyaXRlRmlsZSIsInBhdHRlcm5zIiwiaWdub3JlIiwicGF0dGVybiIsIkFycmF5IiwiZnJvbSIsInB1c2giLCJzdWJzdHJpbmciLCJsZW5ndGgiLCJmaWxlcyIsImN3ZCIsImRvdCIsIm1rZGlycyIsImRlc3QiLCJkZXN0RmlsZW5hbWUiLCJyZW5kZXJGaWxlbmFtZSIsImRhdGEiLCJyZXBsYWNlIiwic3JjRmlsZSIsImRlc3RGaWxlIiwiY29udGVudHMiLCJlanMiLCJyZW5kZXIiLCJ0b1N0cmluZyIsImFzeW5jIiwicm9vdCIsIlByb21pc2UiLCJyZWplY3QiLCJnb3QiLCJzdHJlYW0iLCJvbiIsInJlc3BvbnNlIiwiaGVhZGVycyIsInR5cGUiLCJmaWxlbmFtZSIsIm0iLCJjZCIsIm1hdGNoIiwiRGF0ZSIsIm5vdyIsIm1ha2VUZW1wIiwib3V0IiwiY3JlYXRlV3JpdGVTdHJlYW0iLCJzdGF0U3luYyIsInNpemUiLCJwaXBlIiwiZXh0cmFjdERlc3QiLCJkaXJuYW1lIiwiZW1pdCIsInBlcmNlbnQiLCJkaXIiLCJicmFuY2giLCJjb21taXR0aXNoIiwiY21kIiwiZ2l0IiwiYXJncyIsImdldERlZmF1bHRSZXByZXNlbnRhdGlvbiIsInNzaCIsIm5vQ29tbWl0dGlzaCIsImh0dHBzIiwibm9HaXRQbHVzIiwicHJvamVjdCIsInN0ZGVyciIsInRyaW0iLCJmb3JFYWNoIiwibGluZSIsIm1ldGEiLCJwcm9tcHRzIiwic3RhdCIsImZvcmNlIiwiaXNEaXJlY3RvcnkiLCJTZXQiLCJEZWZhdWx0RmlsdGVycyIsImlzQXJyYXkiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsImZpbHRlciIsIm9wIiwiaGFzIiwiZGVsZXRlIiwiZGVzY3JpcHRvciIsIk9iamVjdCIsImVudHJpZXMiLCJrZXlzIiwicmVhZEpzb24iLCJkaXJTeW5jIiwibW9kZSIsInVuc2FmZUNsZWFudXAiLCJ2ZXJzaW9uIiwid2FsayIsInJlbmFtZVN5bmMiLCJjYWNoZURpciIsIm5wbUFyZ3MiLCJOT19VUERBVEVfTk9USUZJRVIiLCJucG1fY29uZmln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