template-kit
Version:
Project template toolkit
785 lines (636 loc) • 84.9 kB
JavaScript
"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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