@naandalist/patch-package
Version:
Fix broken node modules with no fuss
457 lines (439 loc) • 68.7 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.logPatchSequenceError = exports.makePatch = void 0;
const chalk_1 = __importDefault(require("chalk"));
const console_1 = __importDefault(require("console"));
const fs_1 = require("fs");
const fs_extra_1 = require("fs-extra");
const tmp_1 = require("tmp");
const zlib_1 = require("zlib");
const applyPatches_1 = require("./applyPatches");
const createIssue_1 = require("./createIssue");
const filterFiles_1 = require("./filterFiles");
const getPackageResolution_1 = require("./getPackageResolution");
const getPackageVersion_1 = require("./getPackageVersion");
const hash_1 = require("./hash");
const PackageDetails_1 = require("./PackageDetails");
const parse_1 = require("./patch/parse");
const patchFs_1 = require("./patchFs");
const path_1 = require("./path");
const resolveRelativeFileDependencies_1 = require("./resolveRelativeFileDependencies");
const spawnSafe_1 = require("./spawnSafe");
const stateFile_1 = require("./stateFile");
function printNoPackageFoundError(packageName, packageJsonPath) {
console_1.default.log(`No such package ${packageName}
File not found: ${packageJsonPath}`);
}
function makePatch({ packagePathSpecifier, appPath, packageManager, includePaths, excludePaths, patchDir, createIssue, mode, }) {
var _a, _b, _c, _d, _e, _f, _g;
const packageDetails = (0, PackageDetails_1.getPatchDetailsFromCliString)(packagePathSpecifier);
if (!packageDetails) {
console_1.default.log("No such package", packagePathSpecifier);
return;
}
const state = (0, stateFile_1.getPatchApplicationState)(packageDetails);
const isRebasing = (_a = state === null || state === void 0 ? void 0 : state.isRebasing) !== null && _a !== void 0 ? _a : false;
// If we are rebasing and no patches have been applied, --append is the only valid option because
// there are no previous patches to overwrite/update
if (isRebasing &&
(state === null || state === void 0 ? void 0 : state.patches.filter((p) => p.didApply).length) === 0 &&
mode.type === "overwrite_last") {
mode = { type: "append", name: "initial" };
}
if (isRebasing && state) {
(0, stateFile_1.verifyAppliedPatches)({ appPath, patchDir, state });
}
if (mode.type === "overwrite_last" &&
isRebasing &&
(state === null || state === void 0 ? void 0 : state.patches.length) === 0) {
mode = { type: "append", name: "initial" };
}
const existingPatches = (0, patchFs_1.getGroupedPatches)(patchDir).pathSpecifierToPatchFiles[packageDetails.pathSpecifier] || [];
// apply all existing patches if appending
// otherwise apply all but the last
const previouslyAppliedPatches = state === null || state === void 0 ? void 0 : state.patches.filter((p) => p.didApply);
const patchesToApplyBeforeDiffing = isRebasing
? mode.type === "append"
? existingPatches.slice(0, previouslyAppliedPatches.length)
: state.patches[state.patches.length - 1].didApply
? existingPatches.slice(0, previouslyAppliedPatches.length - 1)
: existingPatches.slice(0, previouslyAppliedPatches.length)
: mode.type === "append"
? existingPatches
: existingPatches.slice(0, -1);
if (createIssue && mode.type === "append") {
console_1.default.log("--create-issue is not compatible with --append.");
process.exit(1);
}
if (createIssue && isRebasing) {
console_1.default.log("--create-issue is not compatible with rebasing.");
process.exit(1);
}
const numPatchesAfterCreate = mode.type === "append" || existingPatches.length === 0
? existingPatches.length + 1
: existingPatches.length;
const vcs = (0, createIssue_1.getPackageVCSDetails)(packageDetails);
const canCreateIssue = !isRebasing &&
(0, createIssue_1.shouldRecommendIssue)(vcs) &&
numPatchesAfterCreate === 1 &&
mode.type !== "append";
const appPackageJson = require((0, path_1.join)(appPath, "package.json"));
const packagePath = (0, path_1.join)(appPath, packageDetails.path);
const packageJsonPath = (0, path_1.join)(packagePath, "package.json");
if (!(0, fs_extra_1.existsSync)(packageJsonPath)) {
printNoPackageFoundError(packagePathSpecifier, packageJsonPath);
process.exit(1);
}
const tmpRepo = (0, tmp_1.dirSync)({ unsafeCleanup: true });
const tmpRepoPackagePath = (0, path_1.join)(tmpRepo.name, packageDetails.path);
const tmpRepoNpmRoot = tmpRepoPackagePath.slice(0, -`/node_modules/${packageDetails.name}`.length);
const tmpRepoPackageJsonPath = (0, path_1.join)(tmpRepoNpmRoot, "package.json");
try {
const patchesDir = (0, path_1.resolve)((0, path_1.join)(appPath, patchDir));
console_1.default.info(chalk_1.default.grey("•"), "Creating temporary folder");
// make a blank package.json
(0, fs_extra_1.mkdirpSync)(tmpRepoNpmRoot);
(0, fs_extra_1.writeFileSync)(tmpRepoPackageJsonPath, JSON.stringify({
// support `corepack` enabled without `.yarn/releases`
packageManager: appPackageJson.packageManager,
dependencies: {
[packageDetails.name]: (0, getPackageResolution_1.getPackageResolution)({
packageDetails,
packageManager,
appPath,
}),
},
resolutions: (0, resolveRelativeFileDependencies_1.resolveRelativeFileDependencies)(appPath, appPackageJson.resolutions || {}),
}));
const packageVersion = (0, getPackageVersion_1.getPackageVersion)((0, path_1.join)((0, path_1.resolve)(packageDetails.path), "package.json"));
[
".npmrc",
".yarnrc",
".yarnrc.yml",
// don't include the whole `.yarn` directory which could contain huge `cache`
".yarn/plugins",
".yarn/releases",
].forEach((rcFile) => {
const rcPath = (0, path_1.join)(appPath, rcFile);
if ((0, fs_extra_1.existsSync)(rcPath)) {
(0, fs_extra_1.copySync)(rcPath, (0, path_1.join)(tmpRepo.name, rcFile), { dereference: true });
}
});
if (packageManager === "yarn") {
console_1.default.info(chalk_1.default.grey("•"), `Installing ${packageDetails.name}@${packageVersion} with yarn`);
const yarnArgs = ["install"];
const yarnVersionCmd = (0, spawnSafe_1.spawnSafeSync)(`yarn`, ["--version"], {
cwd: tmpRepoNpmRoot,
logStdErrOnError: false,
});
const isYarnV1 = yarnVersionCmd.stdout.toString().startsWith("1.");
if (isYarnV1) {
yarnArgs.push("--ignore-engines");
}
try {
// try first without ignoring scripts in case they are required
// this works in 99.99% of cases
(0, spawnSafe_1.spawnSafeSync)(`yarn`, yarnArgs, {
cwd: tmpRepoNpmRoot,
logStdErrOnError: false,
});
}
catch (e) {
// try again while ignoring scripts in case the script depends on
// an implicit context which we haven't reproduced
(0, spawnSafe_1.spawnSafeSync)(`yarn`, [...yarnArgs, isYarnV1 ? "--ignore-scripts" : "--mode=skip-build"], {
cwd: tmpRepoNpmRoot,
});
}
}
else {
console_1.default.info(chalk_1.default.grey("•"), `Installing ${packageDetails.name}@${packageVersion} with npm`);
try {
// try first without ignoring scripts in case they are required
// this works in 99.99% of cases
(0, spawnSafe_1.spawnSafeSync)(`npm`, ["i", "--force"], {
cwd: tmpRepoNpmRoot,
logStdErrOnError: false,
stdio: "ignore",
});
}
catch (e) {
// try again while ignoring scripts in case the script depends on
// an implicit context which we haven't reproduced
(0, spawnSafe_1.spawnSafeSync)(`npm`, ["i", "--ignore-scripts", "--force"], {
cwd: tmpRepoNpmRoot,
stdio: "ignore",
});
}
}
const git = (...args) => (0, spawnSafe_1.spawnSafeSync)("git", args, {
cwd: tmpRepo.name,
env: Object.assign(Object.assign({}, process.env), { HOME: tmpRepo.name }),
maxBuffer: 1024 * 1024 * 100,
});
// remove nested node_modules just to be safe
(0, fs_extra_1.removeSync)((0, path_1.join)(tmpRepoPackagePath, "node_modules"));
// remove .git just to be safe
(0, fs_extra_1.removeSync)((0, path_1.join)(tmpRepoPackagePath, ".git"));
// remove patch-package state file
(0, fs_extra_1.removeSync)((0, path_1.join)(tmpRepoPackagePath, stateFile_1.STATE_FILE_NAME));
// commit the package
console_1.default.info(chalk_1.default.grey("•"), "Diffing your files with clean files");
(0, fs_extra_1.writeFileSync)((0, path_1.join)(tmpRepo.name, ".gitignore"), "!/node_modules\n\n");
git("init");
git("config", "--local", "user.name", "patch-package");
git("config", "--local", "user.email", "patch@pack.age");
// installed git could be configured to always sign, so override that just in case
git("config", "--local", "commit.gpgsign", "false");
// remove ignored files first
(0, filterFiles_1.removeIgnoredFiles)(tmpRepoPackagePath, includePaths, excludePaths);
for (const patchDetails of patchesToApplyBeforeDiffing) {
if (!(0, applyPatches_1.applyPatch)({
patchDetails,
patchDir,
patchFilePath: (0, path_1.join)(appPath, patchDir, patchDetails.patchFilename),
reverse: false,
cwd: tmpRepo.name,
bestEffort: false,
})) {
// TODO: add better error message once --rebase is implemented
console_1.default.log(`Failed to apply patch ${patchDetails.patchFilename} to ${packageDetails.pathSpecifier}`);
process.exit(1);
}
}
git("add", "-f", packageDetails.path);
git("commit", "--allow-empty", "-m", "init");
// replace package with user's version
(0, fs_extra_1.removeSync)(tmpRepoPackagePath);
// pnpm installs packages as symlinks, copySync would copy only the symlink
(0, fs_extra_1.copySync)((0, fs_extra_1.realpathSync)(packagePath), tmpRepoPackagePath);
// remove nested node_modules just to be safe
(0, fs_extra_1.removeSync)((0, path_1.join)(tmpRepoPackagePath, "node_modules"));
// remove .git just to be safe
(0, fs_extra_1.removeSync)((0, path_1.join)(tmpRepoPackagePath, ".git"));
// remove patch-package state file
(0, fs_extra_1.removeSync)((0, path_1.join)(tmpRepoPackagePath, stateFile_1.STATE_FILE_NAME));
// also remove ignored files like before
(0, filterFiles_1.removeIgnoredFiles)(tmpRepoPackagePath, includePaths, excludePaths);
// stage all files
git("add", "-f", packageDetails.path);
// get diff of changes
const diffResult = git("diff", "--cached", "--no-color", "--ignore-space-at-eol", "--no-ext-diff", "--src-prefix=a/", "--dst-prefix=b/");
if (diffResult.stdout.length === 0) {
console_1.default.log(`⁉️ Not creating patch file for package '${packagePathSpecifier}'`);
console_1.default.log(`⁉️ There don't appear to be any changes.`);
if (isRebasing && mode.type === "overwrite_last") {
console_1.default.log("\n💡 To remove a patch file, delete it and then reinstall node_modules from scratch.");
}
process.exit(1);
return;
}
try {
(0, parse_1.parsePatchFile)(diffResult.stdout.toString());
}
catch (e) {
const err = e;
if (err.message.includes("Unexpected file mode string: 120000")) {
console_1.default.log(`
⛔️ ${chalk_1.default.red.bold("ERROR")}
Your changes involve creating symlinks. patch-package does not yet support
symlinks.
️Please use ${chalk_1.default.bold("--include")} and/or ${chalk_1.default.bold("--exclude")} to narrow the scope of your patch if
this was unintentional.
`);
}
else {
const outPath = "./patch-package-error.json.gz";
(0, fs_extra_1.writeFileSync)(outPath, (0, zlib_1.gzipSync)(JSON.stringify({
error: { message: err.message, stack: err.stack },
patch: diffResult.stdout.toString(),
})));
console_1.default.log(`
⛔️ ${chalk_1.default.red.bold("ERROR")}
patch-package was unable to read the patch-file made by git. This should not
happen.
A diagnostic file was written to
${outPath}
Please attach it to a github issue
https://github.com/ds300/patch-package/issues/new?title=New+patch+parse+failed&body=Please+attach+the+diagnostic+file+by+dragging+it+into+here+🙏
Note that this diagnostic file will contain code from the package you were
attempting to patch.
`);
}
process.exit(1);
return;
}
// maybe delete existing
if (mode.type === "append" && !isRebasing && existingPatches.length === 1) {
// if we are appending to an existing patch that doesn't have a sequence number let's rename it
const prevPatch = existingPatches[0];
if (prevPatch.sequenceNumber === undefined) {
const newFileName = createPatchFileName({
packageDetails,
packageVersion,
sequenceNumber: 1,
sequenceName: (_b = prevPatch.sequenceName) !== null && _b !== void 0 ? _b : "initial",
});
const oldPath = (0, path_1.join)(appPath, patchDir, prevPatch.patchFilename);
const newPath = (0, path_1.join)(appPath, patchDir, newFileName);
(0, fs_1.renameSync)(oldPath, newPath);
prevPatch.sequenceNumber = 1;
prevPatch.patchFilename = newFileName;
prevPatch.sequenceName = (_c = prevPatch.sequenceName) !== null && _c !== void 0 ? _c : "initial";
}
}
const lastPatch = existingPatches[state ? state.patches.length - 1 : existingPatches.length - 1];
const sequenceName = mode.type === "append" ? mode.name : lastPatch === null || lastPatch === void 0 ? void 0 : lastPatch.sequenceName;
const sequenceNumber = mode.type === "append"
? ((_d = lastPatch === null || lastPatch === void 0 ? void 0 : lastPatch.sequenceNumber) !== null && _d !== void 0 ? _d : 0) + 1
: lastPatch === null || lastPatch === void 0 ? void 0 : lastPatch.sequenceNumber;
const patchFileName = createPatchFileName({
packageDetails,
packageVersion,
sequenceName,
sequenceNumber,
});
const patchPath = (0, path_1.join)(patchesDir, patchFileName);
if (!(0, fs_extra_1.existsSync)((0, path_1.dirname)(patchPath))) {
// scoped package
(0, fs_extra_1.mkdirSync)((0, path_1.dirname)(patchPath));
}
// if we are inserting a new patch into a sequence we most likely need to update the sequence numbers
if (isRebasing && mode.type === "append") {
const patchesToNudge = existingPatches.slice(state.patches.length);
if (sequenceNumber === undefined) {
throw new Error("sequenceNumber is undefined while rebasing");
}
if (((_e = patchesToNudge[0]) === null || _e === void 0 ? void 0 : _e.sequenceNumber) !== undefined &&
patchesToNudge[0].sequenceNumber <= sequenceNumber) {
let next = sequenceNumber + 1;
for (const p of patchesToNudge) {
const newName = createPatchFileName({
packageDetails,
packageVersion,
sequenceName: p.sequenceName,
sequenceNumber: next++,
});
console_1.default.log("Renaming", chalk_1.default.bold(p.patchFilename), "to", chalk_1.default.bold(newName));
const oldPath = (0, path_1.join)(appPath, patchDir, p.patchFilename);
const newPath = (0, path_1.join)(appPath, patchDir, newName);
(0, fs_1.renameSync)(oldPath, newPath);
}
}
}
(0, fs_extra_1.writeFileSync)(patchPath, diffResult.stdout);
console_1.default.log(`${chalk_1.default.green("✔")} Created file ${(0, path_1.join)(patchDir, patchFileName)}\n`);
const prevState = patchesToApplyBeforeDiffing.map((p) => ({
patchFilename: p.patchFilename,
didApply: true,
patchContentHash: (0, hash_1.hashFile)((0, path_1.join)(appPath, patchDir, p.patchFilename)),
}));
const nextState = [
...prevState,
{
patchFilename: patchFileName,
didApply: true,
patchContentHash: (0, hash_1.hashFile)(patchPath),
},
];
// if any patches come after this one we just made, we should reapply them
let didFailWhileFinishingRebase = false;
if (isRebasing) {
const currentPatches = (0, patchFs_1.getGroupedPatches)((0, path_1.join)(appPath, patchDir))
.pathSpecifierToPatchFiles[packageDetails.pathSpecifier];
const previouslyUnappliedPatches = currentPatches.slice(nextState.length);
if (previouslyUnappliedPatches.length) {
console_1.default.log(`Fast forwarding...`);
for (const patch of previouslyUnappliedPatches) {
const patchFilePath = (0, path_1.join)(appPath, patchDir, patch.patchFilename);
if (!(0, applyPatches_1.applyPatch)({
patchDetails: patch,
patchDir,
patchFilePath,
reverse: false,
cwd: process.cwd(),
bestEffort: false,
})) {
didFailWhileFinishingRebase = true;
logPatchSequenceError({ patchDetails: patch });
nextState.push({
patchFilename: patch.patchFilename,
didApply: false,
patchContentHash: (0, hash_1.hashFile)(patchFilePath),
});
break;
}
else {
console_1.default.log(` ${chalk_1.default.green("✔")} ${patch.patchFilename}`);
nextState.push({
patchFilename: patch.patchFilename,
didApply: true,
patchContentHash: (0, hash_1.hashFile)(patchFilePath),
});
}
}
}
}
if (isRebasing || numPatchesAfterCreate > 1) {
(0, stateFile_1.savePatchApplicationState)({
packageDetails,
patches: nextState,
isRebasing: didFailWhileFinishingRebase,
});
}
else {
(0, stateFile_1.clearPatchApplicationState)(packageDetails);
}
if (canCreateIssue) {
if (createIssue) {
(0, createIssue_1.openIssueCreationLink)({
packageDetails,
patchFileContents: diffResult.stdout.toString(),
packageVersion,
});
}
else {
(0, createIssue_1.maybePrintIssueCreationPrompt)(vcs, packageDetails, packageManager);
}
}
}
catch (e) {
const err = e;
// try to log more useful error message
console_1.default.log(((_f = err.stderr) === null || _f === void 0 ? void 0 : _f.toString()) || ((_g = err.stdout) === null || _g === void 0 ? void 0 : _g.toString()) || e);
throw e;
}
finally {
tmpRepo.removeCallback();
}
}
exports.makePatch = makePatch;
function createPatchFileName({ packageDetails, packageVersion, sequenceNumber, sequenceName, }) {
const packageNames = packageDetails.packageNames
.map((name) => name.replace(/\//g, "+"))
.join("++");
const nameAndVersion = `${packageNames}+${packageVersion}`;
const num = sequenceNumber === undefined
? ""
: `+${sequenceNumber.toString().padStart(3, "0")}`;
const name = !sequenceName ? "" : `+${sequenceName}`;
return `${nameAndVersion}${num}${name}.patch`;
}
function logPatchSequenceError({ patchDetails, }) {
console_1.default.log(`
${chalk_1.default.red.bold("⛔ ERROR")}
Failed to apply patch file ${chalk_1.default.bold(patchDetails.patchFilename)}.
If this patch file is no longer useful, delete it and run
${chalk_1.default.bold(`patch-package`)}
To partially apply the patch (if possible) and output a log of errors to fix, run
${chalk_1.default.bold(`patch-package --partial`)}
After which you should make any required changes inside ${patchDetails.path}, and finally run
${chalk_1.default.bold(`patch-package ${patchDetails.pathSpecifier}`)}
to update the patch file.
`);
}
exports.logPatchSequenceError = logPatchSequenceError;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFrZVBhdGNoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL21ha2VQYXRjaC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxrREFBeUI7QUFDekIsc0RBQTZCO0FBQzdCLDJCQUErQjtBQUMvQix1Q0FRaUI7QUFDakIsNkJBQTZCO0FBQzdCLCtCQUErQjtBQUMvQixpREFBMkM7QUFDM0MsK0NBS3NCO0FBRXRCLCtDQUFrRDtBQUNsRCxpRUFBNkQ7QUFDN0QsMkRBQXVEO0FBQ3ZELGlDQUFpQztBQUNqQyxxREFJeUI7QUFDekIseUNBQThDO0FBQzlDLHVDQUE2QztBQUM3QyxpQ0FBK0M7QUFDL0MsdUZBQW1GO0FBQ25GLDJDQUEyQztBQUMzQywyQ0FPb0I7QUFFcEIsU0FBUyx3QkFBd0IsQ0FDL0IsV0FBbUIsRUFDbkIsZUFBdUI7SUFFdkIsaUJBQU8sQ0FBQyxHQUFHLENBQ1QsbUJBQW1CLFdBQVc7O29CQUVkLGVBQWUsRUFBRSxDQUNsQyxDQUFBO0FBQ0gsQ0FBQztBQUVELFNBQWdCLFNBQVMsQ0FBQyxFQUN4QixvQkFBb0IsRUFDcEIsT0FBTyxFQUNQLGNBQWMsRUFDZCxZQUFZLEVBQ1osWUFBWSxFQUNaLFFBQVEsRUFDUixXQUFXLEVBQ1gsSUFBSSxHQVVMOztJQUNDLE1BQU0sY0FBYyxHQUFHLElBQUEsNkNBQTRCLEVBQUMsb0JBQW9CLENBQUMsQ0FBQTtJQUV6RSxJQUFJLENBQUMsY0FBYyxFQUFFO1FBQ25CLGlCQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixFQUFFLG9CQUFvQixDQUFDLENBQUE7UUFDcEQsT0FBTTtLQUNQO0lBRUQsTUFBTSxLQUFLLEdBQUcsSUFBQSxvQ0FBd0IsRUFBQyxjQUFjLENBQUMsQ0FBQTtJQUN0RCxNQUFNLFVBQVUsR0FBRyxNQUFBLEtBQUssYUFBTCxLQUFLLHVCQUFMLEtBQUssQ0FBRSxVQUFVLG1DQUFJLEtBQUssQ0FBQTtJQUU3QyxpR0FBaUc7SUFDakcsb0RBQW9EO0lB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QUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7OzZCQUVFLGVBQUssQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLGFBQWEsQ0FBQzs7OztJQUkvRCxlQUFLLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQzs7OztJQUkzQixlQUFLLENBQUMsSUFBSSxDQUFDLHlCQUF5QixDQUFDOzswREFHckMsWUFBWSxDQUFDLElBQ2Y7O0lBRUUsZUFBSyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsWUFBWSxDQUFDLGFBQWEsRUFBRSxDQUFDOzs7Q0FHNUQsQ0FBQyxDQUFBO0FBQ0YsQ0FBQztBQTFCRCxzREEwQkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgY2hhbGsgZnJvbSBcImNoYWxrXCJcbmltcG9ydCBjb25zb2xlIGZyb20gXCJjb25zb2xlXCJcbmltcG9ydCB7IHJlbmFtZVN5bmMgfSBmcm9tIFwiZnNcIlxuaW1wb3J0IHtcbiAgY29weVN5bmMsXG4gIGV4aXN0c1N5bmMsXG4gIG1rZGlycFN5bmMsXG4gIG1rZGlyU3luYyxcbiAgcmVhbHBhdGhTeW5jLFxuICByZW1vdmVTeW5jLFxuICB3cml0ZUZpbGVTeW5jLFxufSBmcm9tIFwiZnMtZXh0cmFcIlxuaW1wb3J0IHsgZGlyU3luYyB9IGZyb20gXCJ0bXBcIlxuaW1wb3J0IHsgZ3ppcFN5bmMgfSBmcm9tIFwiemxpYlwiXG5pbXBvcnQgeyBhcHBseVBhdGNoIH0gZnJvbSBcIi4vYXBwbHlQYXRjaGVzXCJcbmltcG9ydCB7XG4gIGdldFBhY2thZ2VWQ1NEZXRhaWxzLFxuICBtYXliZVByaW50SXNzdWVDcmVhdGlvblByb21wdCxcbiAgb3Blbklzc3VlQ3JlYXRpb25MaW5rLFxuICBzaG91bGRSZWNvbW1lbmRJc3N1ZSxcbn0gZnJvbSBcIi4vY3JlYXRlSXNzdWVcIlxuaW1wb3J0IHsgUGFja2FnZU1hbmFnZXIgfSBmcm9tIFwiLi9kZXRlY3RQYWNrYWdlTWFuYWdlclwiXG5pbXBvcnQgeyByZW1vdmVJZ25vcmVkRmlsZXMgfSBmcm9tIFwiLi9maWx0ZXJGaWxlc1wiXG5pbXBvcnQgeyBnZXRQYWNrYWdlUmVzb2x1dGlvbiB9IGZyb20gXCIuL2dldFBhY2thZ2VSZXNvbHV0aW9uXCJcbmltcG9ydCB7IGdldFBhY2thZ2VWZXJzaW9uIH0gZnJvbSBcIi4vZ2V0UGFja2FnZVZlcnNpb25cIlxuaW1wb3J0IHsgaGFzaEZpbGUgfSBmcm9tIFwiLi9oYXNoXCJcbmltcG9ydCB7XG4gIGdldFBhdGNoRGV0YWlsc0Zyb21DbGlTdHJpbmcsXG4gIFBhY2thZ2VEZXRhaWxzLFxuICBQYXRjaGVkUGFja2FnZURldGFpbHMsXG59IGZyb20gXCIuL1BhY2thZ2VEZXRhaWxzXCJcbmltcG9ydCB7IHBhcnNlUGF0Y2hGaWxlIH0gZnJvbSBcIi4vcGF0Y2gvcGFyc2VcIlxuaW1wb3J0IHsgZ2V0R3JvdXBlZFBhdGNoZXMgfSBmcm9tIFwiLi9wYXRjaEZzXCJcbmltcG9ydCB7IGRpcm5hbWUsIGpvaW4sIHJlc29sdmUgfSBmcm9tIFwiLi9wYXRoXCJcbmltcG9ydCB7IHJlc29sdmVSZWxhdGl2ZUZpbGVEZXBlbmRlbmNpZXMgfSBmcm9tIFwiLi9yZXNvbHZlUmVsYXRpdmVGaWxlRGVwZW5kZW5jaWVzXCJcbmltcG9ydCB7IHNwYXduU2FmZVN5bmMgfSBmcm9tIFwiLi9zcGF3blNhZmVcIlxuaW1wb3J0IHtcbiAgY2xlYXJQYXRjaEFwcGxpY2F0aW9uU3RhdGUsXG4gIGdldFBhdGNoQXBwbGljYXRpb25TdGF0ZSxcbiAgUGF0Y2hTdGF0ZSxcbiAgc2F2ZVBhdGNoQXBwbGljYXRpb25TdGF0ZSxcbiAgU1RBVEVfRklMRV9OQU1FLFxuICB2ZXJpZnlBcHBsaWVkUGF0Y2hlcyxcbn0gZnJvbSBcIi4vc3RhdGVGaWxlXCJcblxuZnVuY3Rpb24gcHJpbnROb1BhY2thZ2VGb3VuZEVycm9yKFxuICBwYWNrYWdlTmFtZTogc3RyaW5nLFxuICBwYWNrYWdlSnNvblBhdGg6IHN0cmluZyxcbikge1xuICBjb25zb2xlLmxvZyhcbiAgICBgTm8gc3VjaCBwYWNrYWdlICR7cGFja2FnZU5hbWV9XG5cbiAgRmlsZSBub3QgZm91bmQ6ICR7cGFja2FnZUpzb25QYXRofWAsXG4gIClcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1ha2VQYXRjaCh7XG4gIHBhY2thZ2VQYXRoU3BlY2lmaWVyLFxuICBhcHBQYXRoLFxuICBwYWNrYWdlTWFuYWdlcixcbiAgaW5jbHVkZVBhdGhzLFxuICBleGNsdWRlUGF0aHMsXG4gIHBhdGNoRGlyLFxuICBjcmVhdGVJc3N1ZSxcbiAgbW9kZSxcbn06IHtcbiAgcGFja2FnZVBhdGhTcGVjaWZpZXI6IHN0cmluZ1xuICBhcHBQYXRoOiBzdHJpbmdcbiAgcGFja2FnZU1hbmFnZXI6IFBhY2thZ2VNYW5hZ2VyXG4gIGluY2x1ZGVQYXRoczogUmVnRXhwXG4gIGV4Y2x1ZGVQYXRoczogUmVnRXhwXG4gIHBhdGNoRGlyOiBzdHJpbmdcbiAgY3JlYXRlSXNzdWU6IGJvb2xlYW5cbiAgbW9kZTogeyB0eXBlOiBcIm92ZXJ3cml0ZV9sYXN0XCIgfSB8IHsgdHlwZTogXCJhcHBlbmRcIjsgbmFtZT86IHN0cmluZyB9XG59KSB7XG4gIGNvbnN0IHBhY2thZ2VEZXRhaWxzID0gZ2V0UGF0Y2hEZXRhaWxzRnJvbUNsaVN0cmluZyhwYWNrYWdlUGF0aFNwZWNpZmllcilcblxuICBpZiAoIXBhY2thZ2VEZXRhaWxzKSB7XG4gICAgY29uc29sZS5sb2coXCJObyBzdWNoIHBhY2thZ2VcIiwgcGFja2FnZVBhdGhTcGVjaWZpZXIpXG4gICAgcmV0dXJuXG4gIH1cblxuICBjb25zdCBzdGF0ZSA9IGdldFBhdGNoQXBwbGljYXRpb25TdGF0ZShwYWNrYWdlRGV0YWlscylcbiAgY29uc3QgaXNSZWJhc2luZyA9IHN0YXRlPy5pc1JlYmFzaW5nID8/IGZhbHNlXG5cbiAgLy8gSWYgd2UgYXJlIHJlYmFzaW5nIGFuZCBubyBwYXRjaGVzIGhhdmUgYmVlbiBhcHBsaWVkLCAtLWFwcGVuZCBpcyB0aGUgb25seSB2YWxpZCBvcHRpb24gYmVjYXVzZVxuICAvLyB0aGVyZSBhcmUgbm8gcHJldmlvdXMgcGF0Y2hlcyB0byBvdmVyd3JpdGUvdXBkYXRlXG4gIGlmIChcbiAgICBpc1JlYmFzaW5nICYmXG4gICAgc3RhdGU/LnBhdGNoZXMuZmlsdGVyKChwKSA9PiBwLmRpZEFwcGx5KS5sZW5ndGggPT09IDAgJiZcbiAgICBtb2RlLnR5cGUgPT09IFwib3ZlcndyaXRlX2xhc3RcIlxuICApIHtcbiAgICBtb2RlID0geyB0eXBlOiBcImFwcGVuZFwiLCBuYW1lOiBcImluaXRpYWxcIiB9XG4gIH1cblxuICBpZiAoaXNSZWJhc2luZyAmJiBzdGF0ZSkge1xuICAgIHZlcmlmeUFwcGxpZWRQYXRjaGVzKHsgYXBwUGF0aCwgcGF0Y2hEaXIsIHN0YXRlIH0pXG4gIH1cblxuICBpZiAoXG4gICAgbW9kZS50eXBlID09PSBcIm92ZXJ3cml0ZV9sYXN0XCIgJiZcbiAgICBpc1JlYmFzaW5nICYmXG4gICAgc3RhdGU/LnBhdGNoZXMubGVuZ3RoID09PSAwXG4gICkge1xuICAgIG1vZGUgPSB7IHR5cGU6IFwiYXBwZW5kXCIsIG5hbWU6IFwiaW5pdGlhbFwiIH1cbiAgfVxuXG4gIGNvbnN0IGV4aXN0aW5nUGF0Y2hlcyA9XG4gICAgZ2V0R3JvdXBlZFBhdGNoZXMocGF0Y2hEaXIpLnBhdGhTcGVjaWZpZXJUb1BhdGNoRmlsZXNbXG4gICAgICBwYWNrYWdlRGV0YWlscy5wYXRoU3BlY2lmaWVyXG4gICAgXSB8fCBbXVxuXG4gIC8vIGFwcGx5IGFsbCBleGlzdGluZyBwYXRjaGVzIGlmIGFwcGVuZGluZ1xuICAvLyBvdGhlcndpc2UgYXBwbHkgYWxsIGJ1dCB0aGUgbGFzdFxuICBjb25zdCBwcmV2aW91c2x5QXBwbGllZFBhdGNoZXMgPSBzdGF0ZT8ucGF0Y2hlcy5maWx0ZXIoKHApID0+IHAuZGlkQXBwbHkpXG4gIGNvbnN0IHBhdGNoZXNUb0FwcGx5QmVmb3JlRGlmZmluZzogUGF0Y2hlZFBhY2thZ2VEZXRhaWxzW10gPSBpc1JlYmFzaW5nXG4gICAgPyBtb2RlLnR5cGUgPT09IFwiYXBwZW5kXCJcbiAgICAgID8gZXhpc3RpbmdQYXRjaGVzLnNsaWNlKDAsIHByZXZpb3VzbHlBcHBsaWVkUGF0Y2hlcyEubGVuZ3RoKVxuICAgICAgOiBzdGF0ZSEucGF0Y2hlc1tzdGF0ZSEucGF0Y2hlcy5sZW5ndGggLSAxXS5kaWRBcHBseVxuICAgICAgPyBleGlzdGluZ1BhdGNoZXMuc2xpY2UoMCwgcHJldmlvdXNseUFwcGxpZWRQYXRjaGVzIS5sZW5ndGggLSAxKVxuICAgICAgOiBleGlzdGluZ1BhdGNoZXMuc2xpY2UoMCwgcHJldmlvdXNseUFwcGxpZWRQYXRjaGVzIS5sZW5ndGgpXG4gICAgOiBtb2RlLnR5cGUgPT09IFwiYXBwZW5kXCJcbiAgICA/IGV4aXN0aW5nUGF0Y2hlc1xuICAgIDogZXhpc3RpbmdQYXRjaGVzLnNsaWNlKDAsIC0xKVxuXG4gIGlmIChjcmVhdGVJc3N1ZSAmJiBtb2RlLnR5cGUgPT09IFwiYXBwZW5kXCIpIHtcbiAgICBjb25zb2xlLmxvZyhcIi0tY3JlYXRlLWlzc3VlIGlzIG5vdCBjb21wYXRpYmxlIHdpdGggLS1hcHBlbmQuXCIpXG4gICAgcHJvY2Vzcy5leGl0KDEpXG4gIH1cblxuICBpZiAoY3JlYXRlSXNzdWUgJiYgaXNSZWJhc2luZykge1xuICAgIGNvbnNvbGUubG9nKFwiLS1jcmVhdGUtaXNzdWUgaXMgbm90IGNvbXBhdGlibGUgd2l0aCByZWJhc2luZy5cIilcbiAgICBwcm9jZXNzLmV4aXQoMSlcbiAgfVxuXG4gIGNvbnN0IG51bVBhdGNoZXNBZnRlckNyZWF0ZSA9XG4gICAgbW9kZS50eXBlID09PSBcImFwcGVuZFwiIHx8IGV4aXN0aW5nUGF0Y2hlcy5sZW5ndGggPT09IDBcbiAgICAgID8gZXhpc3RpbmdQYXRjaGVzLmxlbmd0aCArIDFcbiAgICAgIDogZXhpc3RpbmdQYXRjaGVzLmxlbmd0aFxuICBjb25zdCB2Y3MgPSBnZXRQYWNrYWdlVkNTRGV0YWlscyhwYWNrYWdlRGV0YWlscylcbiAgY29uc3QgY2FuQ3JlYXRlSXNzdWUgPVxuICAgICFpc1JlYmFzaW5nICYmXG4gICAgc2hvdWxkUmVjb21tZW5kSXNzdWUodmNzKSAmJlxuICAgIG51bVBhdGNoZXNBZnRlckNyZWF0ZSA9PT0gMSAmJlxuICAgIG1vZGUudHlwZSAhPT0gXCJhcHBlbmRcIlxuXG4gIGNvbnN0IGFwcFBhY2thZ2VKc29uID0gcmVxdWlyZShqb2luKGFwcFBhdGgsIFwicGFja2FnZS5qc29uXCIpKVxuICBjb25zdCBwYWNrYWdlUGF0aCA9IGpvaW4oYXBwUGF0aCwgcGFja2FnZURldGFpbHMucGF0aClcbiAgY29uc3QgcGFja2FnZUpzb25QYXRoID0gam9pbihwYWNrYWdlUGF0aCwgXCJwYWNrYWdlLmpzb25cIilcblxuICBpZiAoIWV4aXN0c1N5bmMocGFja2FnZUpzb25QYXRoKSkge1xuICAgIHByaW50Tm9QYWNrYWdlRm91bmRFcnJvcihwYWNrYWdlUGF0aFNwZWNpZmllciwgcGFja2FnZUpzb25QYXRoKVxuICAgIHByb2Nlc3MuZXhpdCgxKVxuICB9XG5cbiAgY29uc3QgdG1wUmVwbyA9IGRpclN5bmMoeyB1bnNhZmVDbGVhbnVwOiB0cnVlIH0pXG4gIGNvbnN0IHRtcFJlcG9QYWNrYWdlUGF0aCA9IGpvaW4odG1wUmVwby5uYW1lLCBwYWNrYWdlRGV0YWlscy5wYXRoKVxuICBjb25zdCB0bXBSZXBvTnBtUm9vdCA9IHRtcFJlcG9QYWNrYWdlUGF0aC5zbGljZShcbiAgICAwLFxuICAgIC1gL25vZGVfbW9kdWxlcy8ke3BhY2thZ2VEZXRhaWxzLm5hbWV9YC5sZW5ndGgsXG4gIClcblxuICBjb25zdCB0bXBSZXBvUGFja2FnZUpzb25QYXRoID0gam9pbih0bXBSZXBvTnBtUm9vdCwgXCJwYWNrYWdlLmpzb25cIilcblxuICB0cnkge1xuICAgIGNvbnN0IHBhdGNoZXNEaXIgPSByZXNvbHZlKGpvaW4oYXBwUGF0aCwgcGF0Y2hEaXIpKVxuXG4gICAgY29uc29sZS5pbmZvKGNoYWxrLmdyZXkoXCLigKJcIiksIFwiQ3JlYXRpbmcgdGVtcG9yYXJ5IGZvbGRlclwiKVxuXG4gICAgLy8gbWFrZSBhIGJsYW5rIHBhY2thZ2UuanNvblxuICAgIG1rZGlycFN5bmModG1wUmVwb05wbVJvb3QpXG4gICAgd3JpdGVGaWxlU3luYyhcbiAgICAgIHRtcFJlcG9QYWNrYWdlSnNvblBhdGgsXG4gICAgICBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgIC8vIHN1cHBvcnQgYGNvcmVwYWNrYCBlbmFibGVkIHdpdGhvdXQgYC55YXJuL3JlbGVhc2VzYFxuICAgICAgICBwYWNrYWdlTWFuYWdlcjogYXBwUGFja2FnZUpzb24ucGFja2FnZU1hbmFnZXIsXG4gICAgICAgIGRlcGVuZGVuY2llczoge1xuICAgICAgICAgIFtwYWNrYWdlRGV0YWlscy5uYW1lXTogZ2V0UGFja2FnZVJlc29sdXRpb24oe1xuICAgICAgICAgICAgcGFja2FnZURldGFpbHMsXG4gICAgICAgICAgICBwYWNrYWdlTWFuYWdlcixcbiAgICAgICAgICAgIGFwcFBhdGgsXG4gICAgICAgICAgfSksXG4gICAgICAgIH0sXG4gICAgICAgIHJlc29sdXRpb25zOiByZXNvbHZlUmVsYXRpdmVGaWxlRGVwZW5kZW5jaWVzKFxuICAgICAgICAgIGFwcFBhdGgsXG4gICAgICAgICAgYXBwUGFja2FnZUpzb24ucmVzb2x1dGlvbnMgfHwge30sXG4gICAgICAgICksXG4gICAgICB9KSxcbiAgICApXG5cbiAgICBjb25zdCBwYWNrYWdlVmVyc2lvbiA9IGdldFBhY2thZ2VWZXJzaW9uKFxuICAgICAgam9pbihyZXNvbHZlKHBhY2thZ2VEZXRhaWxzLnBhdGgpLCBcInBhY2thZ2UuanNvblwiKSxcbiAgICApXG5cbiAgICAvLyBjb3B5IC5ucG1yYy8ueWFybnJjIGluIGNhc2UgcGFja2FnZXMgYXJlIGhvc3RlZCBpbiBwcml2YXRlIHJlZ2lzdHJ5XG4gICAgLy8gY29weSAueWFybiBkaXJlY3RvcnkgYXMgd2VsbCB0byBlbnN1cmUgaW5zdGFsbGF0aW9ucyB3b3JrIGluIHlhcm4gMlxuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTphbGlnblxuICAgIDtbXG4gICAgICBcIi5ucG1yY1wiLFxuICAgICAgXCIueWFybnJjXCIsXG4gICAgICBcIi55YXJucmMueW1sXCIsXG4gICAgI