@mnaoumov/typescript-dev-toolkit 6.1.0 → 6.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -0
- package/bin/rewrite-changelog.mjs +8 -0
- package/dist/lib/cjs/changelog-grouping.cjs +153 -0
- package/dist/lib/cjs/changelog-grouping.d.cts +70 -0
- package/dist/lib/cjs/changelog-rewrite-cli.cjs +177 -0
- package/dist/lib/cjs/changelog-rewrite-cli.d.cts +105 -0
- package/dist/lib/cjs/changelog-rewrite.cjs +143 -0
- package/dist/lib/cjs/changelog-rewrite.d.cts +108 -0
- package/dist/lib/cjs/index.cjs +10 -1
- package/dist/lib/cjs/index.d.cts +3 -0
- package/dist/lib/cjs/linters/eslint-config.cjs +4 -1
- package/dist/lib/cjs/linters/eslint-rules/in-house-plugin.cjs +3 -1
- package/dist/lib/cjs/linters/eslint-rules/index.cjs +4 -1
- package/dist/lib/cjs/linters/eslint-rules/index.d.cts +1 -0
- package/dist/lib/cjs/linters/eslint-rules/prefer-spread.cjs +114 -0
- package/dist/lib/cjs/linters/eslint-rules/prefer-spread.d.cts +12 -0
- package/dist/lib/cjs/version.cjs +57 -22
- package/dist/lib/cjs/version.d.cts +29 -0
- package/dist/lib/esm/changelog-grouping.d.mts +70 -0
- package/dist/lib/esm/changelog-grouping.mjs +126 -0
- package/dist/lib/esm/changelog-rewrite-cli.d.mts +105 -0
- package/dist/lib/esm/changelog-rewrite-cli.mjs +147 -0
- package/dist/lib/esm/changelog-rewrite.d.mts +108 -0
- package/dist/lib/esm/changelog-rewrite.mjs +118 -0
- package/dist/lib/esm/index.d.mts +3 -0
- package/dist/lib/esm/index.mjs +7 -1
- package/dist/lib/esm/linters/eslint-config.mjs +4 -1
- package/dist/lib/esm/linters/eslint-rules/in-house-plugin.mjs +3 -1
- package/dist/lib/esm/linters/eslint-rules/index.d.mts +1 -0
- package/dist/lib/esm/linters/eslint-rules/index.mjs +3 -1
- package/dist/lib/esm/linters/eslint-rules/prefer-spread.d.mts +12 -0
- package/dist/lib/esm/linters/eslint-rules/prefer-spread.mjs +80 -0
- package/dist/lib/esm/version.d.mts +29 -0
- package/dist/lib/esm/version.mjs +59 -22
- package/linters/eslint-rules/prefer-spread/package.json +6 -0
- package/package.json +2 -1
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* Git operations such as tagging and pushing.
|
|
10
10
|
*/
|
|
11
11
|
import { parseArgs } from 'node:util';
|
|
12
|
+
import type { ChangelogCommitEntry, ChangelogStyle } from './changelog-grouping.cjs';
|
|
12
13
|
/**
|
|
13
14
|
* Options for {@link addUpdatedFilesToGit}.
|
|
14
15
|
*/
|
|
@@ -76,6 +77,16 @@ export interface UpdateChangelogOptions {
|
|
|
76
77
|
* @default the first-parent commit subjects since the previous version
|
|
77
78
|
*/
|
|
78
79
|
readonly changelogFilePath?: string | undefined;
|
|
80
|
+
/**
|
|
81
|
+
* How the section generated from the commit messages is laid out: `grouped` sorts the entries under plain-language
|
|
82
|
+
* headings and counts the maintenance commits instead of listing them, `commits` writes one bullet per first-parent
|
|
83
|
+
* commit. See {@link ChangelogStyle}.
|
|
84
|
+
*
|
|
85
|
+
* Ignored when {@link changelogFilePath} is set.
|
|
86
|
+
*
|
|
87
|
+
* @default `'grouped'`
|
|
88
|
+
*/
|
|
89
|
+
readonly changelogStyle?: ChangelogStyle | undefined;
|
|
79
90
|
/**
|
|
80
91
|
* Whether to open the generated changelog in the editor for an interactive review. When `false`,
|
|
81
92
|
* the changelog is still generated from commit messages, but it is not opened in the editor for
|
|
@@ -102,6 +113,12 @@ export interface UpdateVersionOptions {
|
|
|
102
113
|
* @default the first-parent commit subjects since the previous version
|
|
103
114
|
*/
|
|
104
115
|
readonly changelogFilePath?: string | undefined;
|
|
116
|
+
/**
|
|
117
|
+
* How the section generated from the commit messages is laid out. See {@link UpdateChangelogOptions.changelogStyle}.
|
|
118
|
+
*
|
|
119
|
+
* @default `'grouped'`
|
|
120
|
+
*/
|
|
121
|
+
readonly changelogStyle?: ChangelogStyle | undefined;
|
|
105
122
|
/**
|
|
106
123
|
* Returns the files to attach to the GitHub release. See {@link PublishGitHubReleaseOptions.getReleaseAssetPaths}.
|
|
107
124
|
*/
|
|
@@ -334,6 +351,9 @@ export declare const VERSION_ARGUMENT_OPTIONS: {
|
|
|
334
351
|
readonly 'changelog-file': {
|
|
335
352
|
readonly type: "string";
|
|
336
353
|
};
|
|
354
|
+
readonly 'changelog-style': {
|
|
355
|
+
readonly type: "string";
|
|
356
|
+
};
|
|
337
357
|
readonly 'no-build': {
|
|
338
358
|
readonly type: "boolean";
|
|
339
359
|
};
|
|
@@ -381,6 +401,7 @@ export declare function isPreRelease(version: string): boolean;
|
|
|
381
401
|
* value instead and has no default. Recognized flags:
|
|
382
402
|
* - `--changelog-file=<path>` — use this file's contents as the new version's changelog section instead of
|
|
383
403
|
* the commit-derived bullets, and skip the interactive review entirely.
|
|
404
|
+
* - `--changelog-style=<grouped|commits>` — how the commit-derived section is laid out (default `grouped`).
|
|
384
405
|
* - `--no-build` — skip the build step (only safe when the build output already matches the current code).
|
|
385
406
|
* - `--no-changelog-editing` — generate the changelog without opening it for manual review.
|
|
386
407
|
* - `--no-checks` — skip the clean-repo check, format, spellcheck, lint, over-exposure analysis, and tests (the build still runs).
|
|
@@ -406,6 +427,14 @@ export declare function parseVersionArguments($arguments: string[]): ParsedVersi
|
|
|
406
427
|
* @returns A {@link Promise} that resolves when the release has been published.
|
|
407
428
|
*/
|
|
408
429
|
export declare function publishGitHubRelease(newVersion: string, options?: PublishGitHubReleaseOptions): Promise<void>;
|
|
430
|
+
/**
|
|
431
|
+
* Reads one first-parent commit into the parts both changelog styles render: the line {@link toChangelogEntry}
|
|
432
|
+
* describes, the issue references it does not already show, and what else the body says.
|
|
433
|
+
*
|
|
434
|
+
* @param commitMessage - The full commit message.
|
|
435
|
+
* @returns The parts, with bare URLs in the entry and the detail lines autolinked.
|
|
436
|
+
*/
|
|
437
|
+
export declare function toChangelogCommitEntry(commitMessage: string): ChangelogCommitEntry;
|
|
409
438
|
/**
|
|
410
439
|
* Maps the values `parseArgs` reports for {@link VERSION_ARGUMENT_OPTIONS} onto {@link UpdateVersionOptions}.
|
|
411
440
|
*
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/// <reference path="./library-references.d.mts" />
|
|
2
|
+
/**
|
|
3
|
+
* @file
|
|
4
|
+
*
|
|
5
|
+
* Groups the commit-derived entries of a new changelog section into plain-language sections, so the release notes a
|
|
6
|
+
* release writes with nobody reviewing them can be scanned rather than read commit by commit.
|
|
7
|
+
*
|
|
8
|
+
* The input is still the first-parent commit history, so this is a deterministic transformation of what the author
|
|
9
|
+
* already wrote: it sorts entries by their Conventional-Commits type, leaves out the commit types that do not change
|
|
10
|
+
* what a user gets, merges entries that say the same thing, and swaps a `re #<n>` subject for the issue title its body
|
|
11
|
+
* carries. Prose a human (or an agent) writes still goes in through `--changelog-file`.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* How the generated changelog section of a release is laid out.
|
|
15
|
+
*
|
|
16
|
+
* - `grouped` — a one-line summary, then the entries under `### Breaking changes`, `### New`, `### Fixed`,
|
|
17
|
+
* `### Improved`, `### Documentation` and `### Other changes`, with maintenance commits counted rather than listed.
|
|
18
|
+
* - `commits` — one bullet per first-parent commit, in history order, as every release wrote before `grouped` existed.
|
|
19
|
+
*/
|
|
20
|
+
export type ChangelogStyle = 'commits' | 'grouped';
|
|
21
|
+
/**
|
|
22
|
+
* Every {@link ChangelogStyle}, in the order the `--changelog-style` error lists them.
|
|
23
|
+
*/
|
|
24
|
+
export declare const CHANGELOG_STYLES: readonly ChangelogStyle[];
|
|
25
|
+
/**
|
|
26
|
+
* One first-parent commit, as {@link renderGroupedChangelogSection} takes it.
|
|
27
|
+
*/
|
|
28
|
+
export interface ChangelogCommitEntry {
|
|
29
|
+
/**
|
|
30
|
+
* The body lines that are neither the entry itself nor an issue reference line nor a breaking-change footer, in
|
|
31
|
+
* order. The first of them is the issue title an issue-closing `re #<n>` merge carries.
|
|
32
|
+
*/
|
|
33
|
+
readonly detailLines: readonly string[];
|
|
34
|
+
/**
|
|
35
|
+
* The changelog line the commit produces before grouping: its subject, or the body line lifted onto a default merge
|
|
36
|
+
* subject.
|
|
37
|
+
*/
|
|
38
|
+
readonly entry: string;
|
|
39
|
+
/**
|
|
40
|
+
* Whether the commit carries a `BREAKING CHANGE:` footer. The `!` marker is read off {@link entry} itself.
|
|
41
|
+
*/
|
|
42
|
+
readonly hasBreakingFooter: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* The issue references the body names that {@link entry} does not already show, rendered as the line shows them.
|
|
45
|
+
*/
|
|
46
|
+
readonly references: readonly string[];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The commit types that change nothing a user of the release gets, so the grouped section counts them instead of
|
|
50
|
+
* listing them. A commit of one of these types that is marked breaking is still listed, under breaking changes.
|
|
51
|
+
*/
|
|
52
|
+
export declare const MAINTENANCE_COMMIT_TYPES: ReadonlySet<string>;
|
|
53
|
+
/**
|
|
54
|
+
* Escapes the square brackets of an issue title outside its code spans, so a title such as `[BUG] Links break` is
|
|
55
|
+
* published as text rather than read as a reference link with no definition (markdownlint's MD052).
|
|
56
|
+
*
|
|
57
|
+
* An issue title is written by whoever opened the issue, and no commit hook ever checks it, so it is the one part of a
|
|
58
|
+
* generated entry that can carry Markdown the author never meant. A bracket already escaped is left as it is.
|
|
59
|
+
*
|
|
60
|
+
* @param text - The issue title.
|
|
61
|
+
* @returns The title with every unescaped `[` and `]` outside a code span preceded by a backslash.
|
|
62
|
+
*/
|
|
63
|
+
export declare function escapeLinkBrackets(text: string): string;
|
|
64
|
+
/**
|
|
65
|
+
* Renders the body of a new changelog section in the {@link ChangelogStyle} `grouped` layout.
|
|
66
|
+
*
|
|
67
|
+
* @param entries - The first-parent commits since the previous release, in `git log` order.
|
|
68
|
+
* @returns The section body, without its `## <version>` heading and without a trailing newline.
|
|
69
|
+
*/
|
|
70
|
+
export declare function renderGroupedChangelogSection(entries: readonly ChangelogCommitEntry[]): string;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/*
|
|
2
|
+
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
|
3
|
+
if you want to view the source, please visit the github repository of this plugin
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const CHANGELOG_STYLES = ["grouped", "commits"];
|
|
7
|
+
const MAINTENANCE_COMMIT_TYPES = /* @__PURE__ */ new Set(["build", "chore", "ci", "refactor", "style", "test"]);
|
|
8
|
+
const BREAKING_SECTION = { heading: "Breaking changes", plural: "breaking changes", singular: "breaking change" };
|
|
9
|
+
const NEW_SECTION = { heading: "New", plural: "new features", singular: "new feature" };
|
|
10
|
+
const FIXED_SECTION = { heading: "Fixed", plural: "fixes", singular: "fix" };
|
|
11
|
+
const IMPROVED_SECTION = { heading: "Improved", plural: "improvements", singular: "improvement" };
|
|
12
|
+
const DOCUMENTATION_SECTION = { heading: "Documentation", plural: "documentation changes", singular: "documentation change" };
|
|
13
|
+
const OTHER_SECTION = { heading: "Other changes", plural: "other changes", singular: "other change" };
|
|
14
|
+
const SECTIONS = [BREAKING_SECTION, NEW_SECTION, FIXED_SECTION, IMPROVED_SECTION, DOCUMENTATION_SECTION, OTHER_SECTION];
|
|
15
|
+
const SECTIONS_BY_TYPE = /* @__PURE__ */ new Map([
|
|
16
|
+
["docs", DOCUMENTATION_SECTION],
|
|
17
|
+
["feat", NEW_SECTION],
|
|
18
|
+
["fix", FIXED_SECTION],
|
|
19
|
+
["perf", IMPROVED_SECTION]
|
|
20
|
+
]);
|
|
21
|
+
const CONVENTIONAL_ENTRY_REG_EXP = /^(?<type>[a-z]+)(?:\((?<scope>[^()]*)\))?(?<breaking>!)?:\s+(?<description>\S.*)$/i;
|
|
22
|
+
const ISSUE_ONLY_DESCRIPTION_REG_EXP = /^re (?<issue>#\d+)$/i;
|
|
23
|
+
const CODE_SPAN_REG_EXP = /(?<!`)(?<fence>`+)(?!`)[\s\S]*?(?<!`)\k<fence>(?!`)/g;
|
|
24
|
+
const BRACKET_REG_EXP = /\\*[[\]]/g;
|
|
25
|
+
function escapeLinkBrackets(text) {
|
|
26
|
+
const parts = [];
|
|
27
|
+
let lastIndex = 0;
|
|
28
|
+
for (const match of text.matchAll(CODE_SPAN_REG_EXP)) {
|
|
29
|
+
parts.push(escapeBracketsInPlainText(text.slice(lastIndex, match.index)), match[0]);
|
|
30
|
+
lastIndex = match.index + match[0].length;
|
|
31
|
+
}
|
|
32
|
+
parts.push(escapeBracketsInPlainText(text.slice(lastIndex)));
|
|
33
|
+
return parts.join("");
|
|
34
|
+
}
|
|
35
|
+
function renderGroupedChangelogSection(entries) {
|
|
36
|
+
const sectionEntries = /* @__PURE__ */ new Map();
|
|
37
|
+
let maintenanceCount = 0;
|
|
38
|
+
for (const entry of entries) {
|
|
39
|
+
const classified = classifyEntry(entry);
|
|
40
|
+
if (!classified) {
|
|
41
|
+
maintenanceCount++;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const list = sectionEntries.get(classified.section) ?? [];
|
|
45
|
+
sectionEntries.set(classified.section, list);
|
|
46
|
+
const existing = list.find((sectionEntry) => sectionEntry.text === classified.text);
|
|
47
|
+
if (!existing) {
|
|
48
|
+
list.push({ references: [...classified.references], text: classified.text });
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
existing.references = [.../* @__PURE__ */ new Set([...existing.references, ...classified.references])];
|
|
52
|
+
}
|
|
53
|
+
const blocks = [toSummaryLine(sectionEntries, maintenanceCount)];
|
|
54
|
+
for (const section of SECTIONS) {
|
|
55
|
+
const list = sectionEntries.get(section);
|
|
56
|
+
if (!list) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
blocks.push(`### ${section.heading}`, list.map((sectionEntry) => `- ${toEntryLine(sectionEntry)}`).join("\n"));
|
|
60
|
+
}
|
|
61
|
+
return blocks.join("\n\n");
|
|
62
|
+
}
|
|
63
|
+
function classifyEntry(entry) {
|
|
64
|
+
const groups = CONVENTIONAL_ENTRY_REG_EXP.exec(entry.entry)?.groups;
|
|
65
|
+
if (!groups) {
|
|
66
|
+
return { references: entry.references, section: entry.hasBreakingFooter ? BREAKING_SECTION : OTHER_SECTION, text: entry.entry };
|
|
67
|
+
}
|
|
68
|
+
const type = String(groups["type"]).toLowerCase();
|
|
69
|
+
const isBreaking = groups["breaking"] !== void 0 || entry.hasBreakingFooter;
|
|
70
|
+
const section = isBreaking ? BREAKING_SECTION : toTypeSection(type);
|
|
71
|
+
if (!section) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
const description = String(groups["description"]);
|
|
75
|
+
const issue = ISSUE_ONLY_DESCRIPTION_REG_EXP.exec(description)?.groups?.["issue"];
|
|
76
|
+
const issueTitle = entry.detailLines[0];
|
|
77
|
+
const isIssueTitleUsed = issue !== void 0 && issueTitle !== void 0;
|
|
78
|
+
const text = isIssueTitleUsed ? escapeLinkBrackets(issueTitle) : description;
|
|
79
|
+
const references = isIssueTitleUsed ? [issue, ...entry.references] : entry.references;
|
|
80
|
+
const scope = groups["scope"];
|
|
81
|
+
return {
|
|
82
|
+
references,
|
|
83
|
+
section,
|
|
84
|
+
text: scope ? `**${scope}:** ${text}` : text
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function countPhrase(count, section) {
|
|
88
|
+
return `${String(count)} ${count === 1 ? section.singular : section.plural}`;
|
|
89
|
+
}
|
|
90
|
+
function escapeBracketsInPlainText(text) {
|
|
91
|
+
return text.replaceAll(BRACKET_REG_EXP, (match) => {
|
|
92
|
+
const backslashes = match.slice(0, -1);
|
|
93
|
+
const isEscaped = backslashes.replaceAll("\\\\", "") === "\\";
|
|
94
|
+
return isEscaped ? match : `${backslashes}\\${match.slice(-1)}`;
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
function joinPhrases(phrases) {
|
|
98
|
+
const last = phrases.slice(-1).join("");
|
|
99
|
+
return phrases.length === 1 ? last : `${phrases.slice(0, -1).join(", ")} and ${last}`;
|
|
100
|
+
}
|
|
101
|
+
function toEntryLine(sectionEntry) {
|
|
102
|
+
return sectionEntry.references.length === 0 ? sectionEntry.text : `${sectionEntry.text} (${sectionEntry.references.join(", ")})`;
|
|
103
|
+
}
|
|
104
|
+
function toSummaryLine(sectionEntries, maintenanceCount) {
|
|
105
|
+
const phrases = SECTIONS.map((section) => ({ count: sectionEntries.get(section)?.length ?? 0, section })).filter(({ count }) => count > 0).map(({ count, section }) => countPhrase(count, section));
|
|
106
|
+
const isOne = maintenanceCount === 1;
|
|
107
|
+
const maintenance = maintenanceCount === 0 ? "" : ` ${String(maintenanceCount)} maintenance ${isOne ? "commit" : "commits"} (tests, build, CI, refactoring, dependencies) ${isOne ? "is" : "are"} not listed.`;
|
|
108
|
+
if (phrases.length > 0) {
|
|
109
|
+
return `This release has ${joinPhrases(phrases)}.${maintenance}`;
|
|
110
|
+
}
|
|
111
|
+
return maintenanceCount === 0 ? "This release has no changes." : `This release has maintenance changes only.${maintenance}`;
|
|
112
|
+
}
|
|
113
|
+
function toTypeSection(type) {
|
|
114
|
+
const section = SECTIONS_BY_TYPE.get(type);
|
|
115
|
+
if (section) {
|
|
116
|
+
return section;
|
|
117
|
+
}
|
|
118
|
+
return MAINTENANCE_COMMIT_TYPES.has(type) ? null : OTHER_SECTION;
|
|
119
|
+
}
|
|
120
|
+
export {
|
|
121
|
+
CHANGELOG_STYLES,
|
|
122
|
+
MAINTENANCE_COMMIT_TYPES,
|
|
123
|
+
escapeLinkBrackets,
|
|
124
|
+
renderGroupedChangelogSection
|
|
125
|
+
};
|
|
126
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2NoYW5nZWxvZy1ncm91cGluZy50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIEdyb3VwcyB0aGUgY29tbWl0LWRlcml2ZWQgZW50cmllcyBvZiBhIG5ldyBjaGFuZ2Vsb2cgc2VjdGlvbiBpbnRvIHBsYWluLWxhbmd1YWdlIHNlY3Rpb25zLCBzbyB0aGUgcmVsZWFzZSBub3RlcyBhXG4gKiByZWxlYXNlIHdyaXRlcyB3aXRoIG5vYm9keSByZXZpZXdpbmcgdGhlbSBjYW4gYmUgc2Nhbm5lZCByYXRoZXIgdGhhbiByZWFkIGNvbW1pdCBieSBjb21taXQuXG4gKlxuICogVGhlIGlucHV0IGlzIHN0aWxsIHRoZSBmaXJzdC1wYXJlbnQgY29tbWl0IGhpc3RvcnksIHNvIHRoaXMgaXMgYSBkZXRlcm1pbmlzdGljIHRyYW5zZm9ybWF0aW9uIG9mIHdoYXQgdGhlIGF1dGhvclxuICogYWxyZWFkeSB3cm90ZTogaXQgc29ydHMgZW50cmllcyBieSB0aGVpciBDb252ZW50aW9uYWwtQ29tbWl0cyB0eXBlLCBsZWF2ZXMgb3V0IHRoZSBjb21taXQgdHlwZXMgdGhhdCBkbyBub3QgY2hhbmdlXG4gKiB3aGF0IGEgdXNlciBnZXRzLCBtZXJnZXMgZW50cmllcyB0aGF0IHNheSB0aGUgc2FtZSB0aGluZywgYW5kIHN3YXBzIGEgYHJlICM8bj5gIHN1YmplY3QgZm9yIHRoZSBpc3N1ZSB0aXRsZSBpdHMgYm9keVxuICogY2Fycmllcy4gUHJvc2UgYSBodW1hbiAob3IgYW4gYWdlbnQpIHdyaXRlcyBzdGlsbCBnb2VzIGluIHRocm91Z2ggYC0tY2hhbmdlbG9nLWZpbGVgLlxuICovXG5cbi8qKlxuICogSG93IHRoZSBnZW5lcmF0ZWQgY2hhbmdlbG9nIHNlY3Rpb24gb2YgYSByZWxlYXNlIGlzIGxhaWQgb3V0LlxuICpcbiAqIC0gYGdyb3VwZWRgIFx1MjAxNCBhIG9uZS1saW5lIHN1bW1hcnksIHRoZW4gdGhlIGVudHJpZXMgdW5kZXIgYCMjIyBCcmVha2luZyBjaGFuZ2VzYCwgYCMjIyBOZXdgLCBgIyMjIEZpeGVkYCxcbiAqICAgYCMjIyBJbXByb3ZlZGAsIGAjIyMgRG9jdW1lbnRhdGlvbmAgYW5kIGAjIyMgT3RoZXIgY2hhbmdlc2AsIHdpdGggbWFpbnRlbmFuY2UgY29tbWl0cyBjb3VudGVkIHJhdGhlciB0aGFuIGxpc3RlZC5cbiAqIC0gYGNvbW1pdHNgIFx1MjAxNCBvbmUgYnVsbGV0IHBlciBmaXJzdC1wYXJlbnQgY29tbWl0LCBpbiBoaXN0b3J5IG9yZGVyLCBhcyBldmVyeSByZWxlYXNlIHdyb3RlIGJlZm9yZSBgZ3JvdXBlZGAgZXhpc3RlZC5cbiAqL1xuZXhwb3J0IHR5cGUgQ2hhbmdlbG9nU3R5bGUgPSAnY29tbWl0cycgfCAnZ3JvdXBlZCc7XG5cbi8qKlxuICogRXZlcnkge0BsaW5rIENoYW5nZWxvZ1N0eWxlfSwgaW4gdGhlIG9yZGVyIHRoZSBgLS1jaGFuZ2Vsb2ctc3R5bGVgIGVycm9yIGxpc3RzIHRoZW0uXG4gKi9cbmV4cG9ydCBjb25zdCBDSEFOR0VMT0dfU1RZTEVTOiByZWFkb25seSBDaGFuZ2Vsb2dTdHlsZVtdID0gWydncm91cGVkJywgJ2NvbW1pdHMnXTtcblxuLyoqXG4gKiBPbmUgZmlyc3QtcGFyZW50IGNvbW1pdCwgYXMge0BsaW5rIHJlbmRlckdyb3VwZWRDaGFuZ2Vsb2dTZWN0aW9ufSB0YWtlcyBpdC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDaGFuZ2Vsb2dDb21taXRFbnRyeSB7XG4gIC8qKlxuICAgKiBUaGUgYm9keSBsaW5lcyB0aGF0IGFyZSBuZWl0aGVyIHRoZSBlbnRyeSBpdHNlbGYgbm9yIGFuIGlzc3VlIHJlZmVyZW5jZSBsaW5lIG5vciBhIGJyZWFraW5nLWNoYW5nZSBmb290ZXIsIGluXG4gICAqIG9yZGVyLiBUaGUgZmlyc3Qgb2YgdGhlbSBpcyB0aGUgaXNzdWUgdGl0bGUgYW4gaXNzdWUtY2xvc2luZyBgcmUgIzxuPmAgbWVyZ2UgY2Fycmllcy5cbiAgICovXG4gIHJlYWRvbmx5IGRldGFpbExpbmVzOiByZWFkb25seSBzdHJpbmdbXTtcblxuICAvKipcbiAgICogVGhlIGNoYW5nZWxvZyBsaW5lIHRoZSBjb21taXQgcHJvZHVjZXMgYmVmb3JlIGdyb3VwaW5nOiBpdHMgc3ViamVjdCwgb3IgdGhlIGJvZHkgbGluZSBsaWZ0ZWQgb250byBhIGRlZmF1bHQgbWVyZ2VcbiAgICogc3ViamVjdC5cbiAgICovXG4gIHJlYWRvbmx5IGVudHJ5OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIGNvbW1pdCBjYXJyaWVzIGEgYEJSRUFLSU5HIENIQU5HRTpgIGZvb3Rlci4gVGhlIGAhYCBtYXJrZXIgaXMgcmVhZCBvZmYge0BsaW5rIGVudHJ5fSBpdHNlbGYuXG4gICAqL1xuICByZWFkb25seSBoYXNCcmVha2luZ0Zvb3RlcjogYm9vbGVhbjtcblxuICAvKipcbiAgICogVGhlIGlzc3VlIHJlZmVyZW5jZXMgdGhlIGJvZHkgbmFtZXMgdGhhdCB7QGxpbmsgZW50cnl9IGRvZXMgbm90IGFscmVhZHkgc2hvdywgcmVuZGVyZWQgYXMgdGhlIGxpbmUgc2hvd3MgdGhlbS5cbiAgICovXG4gIHJlYWRvbmx5IHJlZmVyZW5jZXM6IHJlYWRvbmx5IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIFRoZSBjb21taXQgdHlwZXMgdGhhdCBjaGFuZ2Ugbm90aGluZyBhIHVzZXIgb2YgdGhlIHJlbGVhc2UgZ2V0cywgc28gdGhlIGdyb3VwZWQgc2VjdGlvbiBjb3VudHMgdGhlbSBpbnN0ZWFkIG9mXG4gKiBsaXN0aW5nIHRoZW0uIEEgY29tbWl0IG9mIG9uZSBvZiB0aGVzZSB0eXBlcyB0aGF0IGlzIG1hcmtlZCBicmVha2luZyBpcyBzdGlsbCBsaXN0ZWQsIHVuZGVyIGJyZWFraW5nIGNoYW5nZXMuXG4gKi9cbmV4cG9ydCBjb25zdCBNQUlOVEVOQU5DRV9DT01NSVRfVFlQRVM6IFJlYWRvbmx5U2V0PHN0cmluZz4gPSBuZXcgU2V0KFsnYnVpbGQnLCAnY2hvcmUnLCAnY2knLCAncmVmYWN0b3InLCAnc3R5bGUnLCAndGVzdCddKTtcblxuaW50ZXJmYWNlIENsYXNzaWZpZWRFbnRyeSB7XG4gIHJlYWRvbmx5IHJlZmVyZW5jZXM6IHJlYWRvbmx5IHN0cmluZ1tdO1xuICByZWFkb25seSBzZWN0aW9uOiBTZWN0aW9uRGVmaW5pdGlvbjtcbiAgcmVhZG9ubHkgdGV4dDogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgU2VjdGlvbkRlZmluaXRpb24ge1xuICByZWFkb25seSBoZWFkaW5nOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHBsdXJhbDogc3RyaW5nO1xuICByZWFkb25seSBzaW5ndWxhcjogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgU2VjdGlvbkVudHJ5IHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHR5cGVzY3JpcHQtZGV2LXRvb2xraXQvcmVhZG9ubHktaW50ZXJmYWNlLW1lbWJlcnMgLS0gTWVyZ2VkIGVudHJpZXMgY29sbGVjdCByZWZlcmVuY2VzIGluIHBsYWNlLlxuICByZWZlcmVuY2VzOiBzdHJpbmdbXTtcbiAgcmVhZG9ubHkgdGV4dDogc3RyaW5nO1xufVxuXG5jb25zdCBCUkVBS0lOR19TRUNUSU9OOiBTZWN0aW9uRGVmaW5pdGlvbiA9IHsgaGVhZGluZzogJ0JyZWFraW5nIGNoYW5nZXMnLCBwbHVyYWw6ICdicmVha2luZyBjaGFuZ2VzJywgc2luZ3VsYXI6ICdicmVha2luZyBjaGFuZ2UnIH07XG5jb25zdCBORVdfU0VDVElPTjogU2VjdGlvbkRlZmluaXRpb24gPSB7IGhlYWRpbmc6ICdOZXcnLCBwbHVyYWw6ICduZXcgZmVhdHVyZXMnLCBzaW5ndWxhcjogJ25ldyBmZWF0dXJlJyB9O1xuY29uc3QgRklYRURfU0VDVElPTjogU2VjdGlvbkRlZmluaXRpb24gPSB7IGhlYWRpbmc6ICdGaXhlZCcsIHBsdXJhbDogJ2ZpeGVzJywgc2luZ3VsYXI6ICdmaXgnIH07XG5jb25zdCBJTVBST1ZFRF9TRUNUSU9OOiBTZWN0aW9uRGVmaW5pdGlvbiA9IHsgaGVhZGluZzogJ0ltcHJvdmVkJywgcGx1cmFsOiAnaW1wcm92ZW1lbnRzJywgc2luZ3VsYXI6ICdpbXByb3ZlbWVudCcgfTtcbmNvbnN0IERPQ1VNRU5UQVRJT05fU0VDVElPTjogU2VjdGlvbkRlZmluaXRpb24gPSB7IGhlYWRpbmc6ICdEb2N1bWVudGF0aW9uJywgcGx1cmFsOiAnZG9jdW1lbnRhdGlvbiBjaGFuZ2VzJywgc2luZ3VsYXI6ICdkb2N1bWVudGF0aW9uIGNoYW5nZScgfTtcbmNvbnN0IE9USEVSX1NFQ1RJT046IFNlY3Rpb25EZWZpbml0aW9uID0geyBoZWFkaW5nOiAnT3RoZXIgY2hhbmdlcycsIHBsdXJhbDogJ290aGVyIGNoYW5nZXMnLCBzaW5ndWxhcjogJ290aGVyIGNoYW5nZScgfTtcblxuLyoqXG4gKiBUaGUgc2VjdGlvbnMsIGluIHRoZSBvcmRlciB0aGV5IGFyZSByZW5kZXJlZCBhbmQgc3VtbWFyaXplZC5cbiAqL1xuY29uc3QgU0VDVElPTlM6IHJlYWRvbmx5IFNlY3Rpb25EZWZpbml0aW9uW10gPSBbQlJFQUtJTkdfU0VDVElPTiwgTkVXX1NFQ1RJT04sIEZJWEVEX1NFQ1RJT04sIElNUFJPVkVEX1NFQ1RJT04sIERPQ1VNRU5UQVRJT05fU0VDVElPTiwgT1RIRVJfU0VDVElPTl07XG5cbmNvbnN0IFNFQ1RJT05TX0JZX1RZUEUgPSBuZXcgTWFwPHN0cmluZywgU2VjdGlvbkRlZmluaXRpb24+KFtcbiAgWydkb2NzJywgRE9DVU1FTlRBVElPTl9TRUNUSU9OXSxcbiAgWydmZWF0JywgTkVXX1NFQ1RJT05dLFxuICBbJ2ZpeCcsIEZJWEVEX1NFQ1RJT05dLFxuICBbJ3BlcmYnLCBJTVBST1ZFRF9TRUNUSU9OXVxuXSk7XG5cbmNvbnN0IENPTlZFTlRJT05BTF9FTlRSWV9SRUdfRVhQID0gL14oPzx0eXBlPlthLXpdKykoPzpcXCgoPzxzY29wZT5bXigpXSopXFwpKT8oPzxicmVha2luZz4hKT86XFxzKyg/PGRlc2NyaXB0aW9uPlxcUy4qKSQvaTtcblxuLyoqXG4gKiBBbiBpc3N1ZS1jbG9zaW5nIG1lcmdlIHN1YmplY3QsIHdob3NlIHJlYWRhYmxlIGhhbGYgaXMgdGhlIGlzc3VlIHRpdGxlIG9uIHRoZSBib2R5J3MgZmlyc3QgbGluZS5cbiAqL1xuY29uc3QgSVNTVUVfT05MWV9ERVNDUklQVElPTl9SRUdfRVhQID0gL15yZSAoPzxpc3N1ZT4jXFxkKykkL2k7XG5cbi8qKlxuICogQSBjb2RlIHNwYW46IGEgYmFja3RpY2sgcnVuLCB0aGUgc2hvcnRlc3QgdGV4dCB1cCB0byBhIGJhY2t0aWNrIHJ1biBvZiB0aGUgc2FtZSBsZW5ndGguXG4gKi9cbmNvbnN0IENPREVfU1BBTl9SRUdfRVhQID0gLyg/PCFgKSg/PGZlbmNlPmArKSg/IWApW1xcc1xcU10qPyg/PCFgKVxcazxmZW5jZT4oPyFgKS9nO1xuXG4vKipcbiAqIEEgc3F1YXJlIGJyYWNrZXQgYW5kIHRoZSBiYWNrc2xhc2hlcyByaWdodCBiZWZvcmUgaXQuXG4gKi9cbmNvbnN0IEJSQUNLRVRfUkVHX0VYUCA9IC9cXFxcKltbXFxdXS9nO1xuXG4vKipcbiAqIEVzY2FwZXMgdGhlIHNxdWFyZSBicmFja2V0cyBvZiBhbiBpc3N1ZSB0aXRsZSBvdXRzaWRlIGl0cyBjb2RlIHNwYW5zLCBzbyBhIHRpdGxlIHN1Y2ggYXMgYFtCVUddIExpbmtzIGJyZWFrYCBpc1xuICogcHVibGlzaGVkIGFzIHRleHQgcmF0aGVyIHRoYW4gcmVhZCBhcyBhIHJlZmVyZW5jZSBsaW5rIHdpdGggbm8gZGVmaW5pdGlvbiAobWFya2Rvd25saW50J3MgTUQwNTIpLlxuICpcbiAqIEFuIGlzc3VlIHRpdGxlIGlzIHdyaXR0ZW4gYnkgd2hvZXZlciBvcGVuZWQgdGhlIGlzc3VlLCBhbmQgbm8gY29tbWl0IGhvb2sgZXZlciBjaGVja3MgaXQsIHNvIGl0IGlzIHRoZSBvbmUgcGFydCBvZiBhXG4gKiBnZW5lcmF0ZWQgZW50cnkgdGhhdCBjYW4gY2FycnkgTWFya2Rvd24gdGhlIGF1dGhvciBuZXZlciBtZWFudC4gQSBicmFja2V0IGFscmVhZHkgZXNjYXBlZCBpcyBsZWZ0IGFzIGl0IGlzLlxuICpcbiAqIEBwYXJhbSB0ZXh0IC0gVGhlIGlzc3VlIHRpdGxlLlxuICogQHJldHVybnMgVGhlIHRpdGxlIHdpdGggZXZlcnkgdW5lc2NhcGVkIGBbYCBhbmQgYF1gIG91dHNpZGUgYSBjb2RlIHNwYW4gcHJlY2VkZWQgYnkgYSBiYWNrc2xhc2guXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlc2NhcGVMaW5rQnJhY2tldHModGV4dDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgcGFydHM6IHN0cmluZ1tdID0gW107XG4gIGxldCBsYXN0SW5kZXggPSAwO1xuICBmb3IgKGNvbnN0IG1hdGNoIG9mIHRleHQubWF0Y2hBbGwoQ09ERV9TUEFOX1JFR19FWFApKSB7XG4gICAgcGFydHMucHVzaChlc2NhcGVCcmFja2V0c0luUGxhaW5UZXh0KHRleHQuc2xpY2UobGFzdEluZGV4LCBtYXRjaC5pbmRleCkpLCBtYXRjaFswXSk7XG4gICAgbGFzdEluZGV4ID0gbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGg7XG4gIH1cblxuICBwYXJ0cy5wdXNoKGVzY2FwZUJyYWNrZXRzSW5QbGFpblRleHQodGV4dC5zbGljZShsYXN0SW5kZXgpKSk7XG4gIHJldHVybiBwYXJ0cy5qb2luKCcnKTtcbn1cblxuLyoqXG4gKiBSZW5kZXJzIHRoZSBib2R5IG9mIGEgbmV3IGNoYW5nZWxvZyBzZWN0aW9uIGluIHRoZSB7QGxpbmsgQ2hhbmdlbG9nU3R5bGV9IGBncm91cGVkYCBsYXlvdXQuXG4gKlxuICogQHBhcmFtIGVudHJpZXMgLSBUaGUgZmlyc3QtcGFyZW50IGNvbW1pdHMgc2luY2UgdGhlIHByZXZpb3VzIHJlbGVhc2UsIGluIGBnaXQgbG9nYCBvcmRlci5cbiAqIEByZXR1cm5zIFRoZSBzZWN0aW9uIGJvZHksIHdpdGhvdXQgaXRzIGAjIyA8dmVyc2lvbj5gIGhlYWRpbmcgYW5kIHdpdGhvdXQgYSB0cmFpbGluZyBuZXdsaW5lLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVuZGVyR3JvdXBlZENoYW5nZWxvZ1NlY3Rpb24oZW50cmllczogcmVhZG9ubHkgQ2hhbmdlbG9nQ29tbWl0RW50cnlbXSk6IHN0cmluZyB7XG4gIGNvbnN0IHNlY3Rpb25FbnRyaWVzID0gbmV3IE1hcDxTZWN0aW9uRGVmaW5pdGlvbiwgU2VjdGlvbkVudHJ5W10+KCk7XG4gIGxldCBtYWludGVuYW5jZUNvdW50ID0gMDtcblxuICBmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICBjb25zdCBjbGFzc2lmaWVkID0gY2xhc3NpZnlFbnRyeShlbnRyeSk7XG4gICAgaWYgKCFjbGFzc2lmaWVkKSB7XG4gICAgICBtYWludGVuYW5jZUNvdW50Kys7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBjb25zdCBsaXN0ID0gc2VjdGlvbkVudHJpZXMuZ2V0KGNsYXNzaWZpZWQuc2VjdGlvbikgPz8gW107XG4gICAgc2VjdGlvbkVudHJpZXMuc2V0KGNsYXNzaWZpZWQuc2VjdGlvbiwgbGlzdCk7XG4gICAgY29uc3QgZXhpc3RpbmcgPSBsaXN0LmZpbmQoKHNlY3Rpb25FbnRyeSkgPT4gc2VjdGlvbkVudHJ5LnRleHQgPT09IGNsYXNzaWZpZWQudGV4dCk7XG4gICAgaWYgKCFleGlzdGluZykge1xuICAgICAgbGlzdC5wdXNoKHsgcmVmZXJlbmNlczogWy4uLmNsYXNzaWZpZWQucmVmZXJlbmNlc10sIHRleHQ6IGNsYXNzaWZpZWQudGV4dCB9KTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGV4aXN0aW5nLnJlZmVyZW5jZXMgPSBbLi4ubmV3IFNldChbLi4uZXhpc3RpbmcucmVmZXJlbmNlcywgLi4uY2xhc3NpZmllZC5yZWZlcmVuY2VzXSldO1xuICB9XG5cbiAgY29uc3QgYmxvY2tzID0gW3RvU3VtbWFyeUxpbmUoc2VjdGlvbkVudHJpZXMsIG1haW50ZW5hbmNlQ291bnQpXTtcbiAgZm9yIChjb25zdCBzZWN0aW9uIG9mIFNFQ1RJT05TKSB7XG4gICAgY29uc3QgbGlzdCA9IHNlY3Rpb25FbnRyaWVzLmdldChzZWN0aW9uKTtcbiAgICBpZiAoIWxpc3QpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGJsb2Nrcy5wdXNoKGAjIyMgJHtzZWN0aW9uLmhlYWRpbmd9YCwgbGlzdC5tYXAoKHNlY3Rpb25FbnRyeSkgPT4gYC0gJHt0b0VudHJ5TGluZShzZWN0aW9uRW50cnkpfWApLmpvaW4oJ1xcbicpKTtcbiAgfVxuXG4gIHJldHVybiBibG9ja3Muam9pbignXFxuXFxuJyk7XG59XG5cbmZ1bmN0aW9uIGNsYXNzaWZ5RW50cnkoZW50cnk6IENoYW5nZWxvZ0NvbW1pdEVudHJ5KTogQ2xhc3NpZmllZEVudHJ5IHwgbnVsbCB7XG4gIGNvbnN0IGdyb3VwcyA9IENPTlZFTlRJT05BTF9FTlRSWV9SRUdfRVhQLmV4ZWMoZW50cnkuZW50cnkpPy5ncm91cHM7XG4gIGlmICghZ3JvdXBzKSB7XG4gICAgcmV0dXJuIHsgcmVmZXJlbmNlczogZW50cnkucmVmZXJlbmNlcywgc2VjdGlvbjogZW50cnkuaGFzQnJlYWtpbmdGb290ZXIgPyBCUkVBS0lOR19TRUNUSU9OIDogT1RIRVJfU0VDVElPTiwgdGV4dDogZW50cnkuZW50cnkgfTtcbiAgfVxuXG4gIC8vIFRoZSByZWd1bGFyIGV4cHJlc3Npb24ncyBgdHlwZWAgYW5kIGBkZXNjcmlwdGlvbmAgZ3JvdXBzIGFyZSBub3Qgb3B0aW9uYWwsIHNvIGEgbWF0Y2ggYWx3YXlzIGZpbGxzIHRoZW0uXG4gIGNvbnN0IHR5cGUgPSBTdHJpbmcoZ3JvdXBzWyd0eXBlJ10pLnRvTG93ZXJDYXNlKCk7XG4gIGNvbnN0IGlzQnJlYWtpbmcgPSBncm91cHNbJ2JyZWFraW5nJ10gIT09IHVuZGVmaW5lZCB8fCBlbnRyeS5oYXNCcmVha2luZ0Zvb3RlcjtcbiAgY29uc3Qgc2VjdGlvbiA9IGlzQnJlYWtpbmcgPyBCUkVBS0lOR19TRUNUSU9OIDogdG9UeXBlU2VjdGlvbih0eXBlKTtcbiAgaWYgKCFzZWN0aW9uKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCBkZXNjcmlwdGlvbiA9IFN0cmluZyhncm91cHNbJ2Rlc2NyaXB0aW9uJ10pO1xuICBjb25zdCBpc3N1ZSA9IElTU1VFX09OTFlfREVTQ1JJUFRJT05fUkVHX0VYUC5leGVjKGRlc2NyaXB0aW9uKT8uZ3JvdXBzPy5bJ2lzc3VlJ107XG4gIGNvbnN0IGlzc3VlVGl0bGUgPSBlbnRyeS5kZXRhaWxMaW5lc1swXTtcbiAgY29uc3QgaXNJc3N1ZVRpdGxlVXNlZCA9IGlzc3VlICE9PSB1bmRlZmluZWQgJiYgaXNzdWVUaXRsZSAhPT0gdW5kZWZpbmVkO1xuICBjb25zdCB0ZXh0ID0gaXNJc3N1ZVRpdGxlVXNlZCA/IGVzY2FwZUxpbmtCcmFja2V0cyhpc3N1ZVRpdGxlKSA6IGRlc2NyaXB0aW9uO1xuICBjb25zdCByZWZlcmVuY2VzID0gaXNJc3N1ZVRpdGxlVXNlZCA/IFtpc3N1ZSwgLi4uZW50cnkucmVmZXJlbmNlc10gOiBlbnRyeS5yZWZlcmVuY2VzO1xuICBjb25zdCBzY29wZSA9IGdyb3Vwc1snc2NvcGUnXTtcbiAgcmV0dXJuIHtcbiAgICByZWZlcmVuY2VzLFxuICAgIHNlY3Rpb24sXG4gICAgdGV4dDogc2NvcGUgPyBgKioke3Njb3BlfToqKiAke3RleHR9YCA6IHRleHRcbiAgfTtcbn1cblxuZnVuY3Rpb24gY291bnRQaHJhc2UoY291bnQ6IG51bWJlciwgc2VjdGlvbjogU2VjdGlvbkRlZmluaXRpb24pOiBzdHJpbmcge1xuICByZXR1cm4gYCR7U3RyaW5nKGNvdW50KX0gJHtjb3VudCA9PT0gMSA/IHNlY3Rpb24uc2luZ3VsYXIgOiBzZWN0aW9uLnBsdXJhbH1gO1xufVxuXG5mdW5jdGlvbiBlc2NhcGVCcmFja2V0c0luUGxhaW5UZXh0KHRleHQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiB0ZXh0LnJlcGxhY2VBbGwoQlJBQ0tFVF9SRUdfRVhQLCAobWF0Y2g6IHN0cmluZykgPT4ge1xuICAgIGNvbnN0IGJhY2tzbGFzaGVzID0gbWF0Y2guc2xpY2UoMCwgLTEpO1xuICAgIC8vIEFuIG9kZCBydW4gb2YgYmFja3NsYXNoZXMgZXNjYXBlcyB0aGUgYnJhY2tldDsgYW4gZXZlbiBvbmUgaXMgZXNjYXBlZCBiYWNrc2xhc2hlcyBvbmx5LlxuICAgIGNvbnN0IGlzRXNjYXBlZCA9IGJhY2tzbGFzaGVzLnJlcGxhY2VBbGwoJ1xcXFxcXFxcJywgJycpID09PSAnXFxcXCc7XG4gICAgcmV0dXJuIGlzRXNjYXBlZCA/IG1hdGNoIDogYCR7YmFja3NsYXNoZXN9XFxcXCR7bWF0Y2guc2xpY2UoLTEpfWA7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBqb2luUGhyYXNlcyhwaHJhc2VzOiByZWFkb25seSBzdHJpbmdbXSk6IHN0cmluZyB7XG4gIGNvbnN0IGxhc3QgPSBwaHJhc2VzLnNsaWNlKC0xKS5qb2luKCcnKTtcbiAgcmV0dXJuIHBocmFzZXMubGVuZ3RoID09PSAxID8gbGFzdCA6IGAke3BocmFzZXMuc2xpY2UoMCwgLTEpLmpvaW4oJywgJyl9IGFuZCAke2xhc3R9YDtcbn1cblxuZnVuY3Rpb24gdG9FbnRyeUxpbmUoc2VjdGlvbkVudHJ5OiBTZWN0aW9uRW50cnkpOiBzdHJpbmcge1xuICByZXR1cm4gc2VjdGlvbkVudHJ5LnJlZmVyZW5jZXMubGVuZ3RoID09PSAwID8gc2VjdGlvbkVudHJ5LnRleHQgOiBgJHtzZWN0aW9uRW50cnkudGV4dH0gKCR7c2VjdGlvbkVudHJ5LnJlZmVyZW5jZXMuam9pbignLCAnKX0pYDtcbn1cblxuZnVuY3Rpb24gdG9TdW1tYXJ5TGluZShzZWN0aW9uRW50cmllczogUmVhZG9ubHlNYXA8U2VjdGlvbkRlZmluaXRpb24sIHJlYWRvbmx5IFNlY3Rpb25FbnRyeVtdPiwgbWFpbnRlbmFuY2VDb3VudDogbnVtYmVyKTogc3RyaW5nIHtcbiAgY29uc3QgcGhyYXNlcyA9IFNFQ1RJT05TXG4gICAgLm1hcCgoc2VjdGlvbikgPT4gKHsgY291bnQ6IHNlY3Rpb25FbnRyaWVzLmdldChzZWN0aW9uKT8ubGVuZ3RoID8/IDAsIHNlY3Rpb24gfSkpXG4gICAgLmZpbHRlcigoeyBjb3VudCB9KSA9PiBjb3VudCA+IDApXG4gICAgLm1hcCgoeyBjb3VudCwgc2VjdGlvbiB9KSA9PiBjb3VudFBocmFzZShjb3VudCwgc2VjdGlvbikpO1xuICBjb25zdCBpc09uZSA9IG1haW50ZW5hbmNlQ291bnQgPT09IDE7XG4gIGNvbnN0IG1haW50ZW5hbmNlID0gbWFpbnRlbmFuY2VDb3VudCA9PT0gMFxuICAgID8gJydcbiAgICA6IGAgJHtTdHJpbmcobWFpbnRlbmFuY2VDb3VudCl9IG1haW50ZW5hbmNlICR7aXNPbmUgPyAnY29tbWl0JyA6ICdjb21taXRzJ30gKHRlc3RzLCBidWlsZCwgQ0ksIHJlZmFjdG9yaW5nLCBkZXBlbmRlbmNpZXMpICR7aXNPbmUgPyAnaXMnIDogJ2FyZSd9IG5vdCBsaXN0ZWQuYDtcblxuICBpZiAocGhyYXNlcy5sZW5ndGggPiAwKSB7XG4gICAgcmV0dXJuIGBUaGlzIHJlbGVhc2UgaGFzICR7am9pblBocmFzZXMocGhyYXNlcyl9LiR7bWFpbnRlbmFuY2V9YDtcbiAgfVxuXG4gIHJldHVybiBtYWludGVuYW5jZUNvdW50ID09PSAwID8gJ1RoaXMgcmVsZWFzZSBoYXMgbm8gY2hhbmdlcy4nIDogYFRoaXMgcmVsZWFzZSBoYXMgbWFpbnRlbmFuY2UgY2hhbmdlcyBvbmx5LiR7bWFpbnRlbmFuY2V9YDtcbn1cblxuZnVuY3Rpb24gdG9UeXBlU2VjdGlvbih0eXBlOiBzdHJpbmcpOiBudWxsIHwgU2VjdGlvbkRlZmluaXRpb24ge1xuICBjb25zdCBzZWN0aW9uID0gU0VDVElPTlNfQllfVFlQRS5nZXQodHlwZSk7XG4gIGlmIChzZWN0aW9uKSB7XG4gICAgcmV0dXJuIHNlY3Rpb247XG4gIH1cblxuICByZXR1cm4gTUFJTlRFTkFOQ0VfQ09NTUlUX1RZUEVTLmhhcyh0eXBlKSA/IG51bGwgOiBPVEhFUl9TRUNUSU9OO1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7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
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/// <reference path="./library-references.d.mts" />
|
|
2
|
+
/**
|
|
3
|
+
* @file
|
|
4
|
+
*
|
|
5
|
+
* The `rewrite-changelog` command: rewrites a project's published `CHANGELOG.md` sections, and optionally its GitHub
|
|
6
|
+
* release notes, into the `grouped` layout, by wiring {@link rewriteChangelog} to the real git, `gh` and file system.
|
|
7
|
+
*
|
|
8
|
+
* It changes nothing unless `--write` is passed, so the first run is always a report of what it would do.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* The result of one command the `rewrite-changelog` command runs.
|
|
12
|
+
*/
|
|
13
|
+
export interface RewriteChangelogCommandResult {
|
|
14
|
+
/**
|
|
15
|
+
* The exit code.
|
|
16
|
+
*/
|
|
17
|
+
readonly exitCode: number;
|
|
18
|
+
/**
|
|
19
|
+
* The standard error.
|
|
20
|
+
*/
|
|
21
|
+
readonly stderr: string;
|
|
22
|
+
/**
|
|
23
|
+
* The standard output.
|
|
24
|
+
*/
|
|
25
|
+
readonly stdout: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The outside world of the `rewrite-changelog` command.
|
|
29
|
+
*/
|
|
30
|
+
export interface RewriteChangelogDependencies {
|
|
31
|
+
/**
|
|
32
|
+
* Runs a command in the working directory.
|
|
33
|
+
*
|
|
34
|
+
* @param file - The executable.
|
|
35
|
+
* @param arguments_ - Its arguments.
|
|
36
|
+
* @param input - What to write to its standard input.
|
|
37
|
+
* @returns The result.
|
|
38
|
+
*/
|
|
39
|
+
readonly exec: (file: string, arguments_: readonly string[], input?: string) => RewriteChangelogCommandResult;
|
|
40
|
+
/**
|
|
41
|
+
* Writes one line of the report.
|
|
42
|
+
*
|
|
43
|
+
* @param text - The line.
|
|
44
|
+
*/
|
|
45
|
+
readonly log: (text: string) => void;
|
|
46
|
+
/**
|
|
47
|
+
* Reads a text file.
|
|
48
|
+
*
|
|
49
|
+
* @param path - The path.
|
|
50
|
+
* @returns The content.
|
|
51
|
+
*/
|
|
52
|
+
readonly readFile: (path: string) => string;
|
|
53
|
+
/**
|
|
54
|
+
* Writes a text file.
|
|
55
|
+
*
|
|
56
|
+
* @param path - The path.
|
|
57
|
+
* @param content - The content.
|
|
58
|
+
*/
|
|
59
|
+
readonly writeFile: (path: string, content: string) => void;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The options of the `rewrite-changelog` command.
|
|
63
|
+
*/
|
|
64
|
+
export interface RewriteChangelogOptions {
|
|
65
|
+
/**
|
|
66
|
+
* The `CHANGELOG.md` to rewrite.
|
|
67
|
+
*/
|
|
68
|
+
readonly changelogPath: string;
|
|
69
|
+
/**
|
|
70
|
+
* Whether a GitHub release whose notes are no longer its changelog section as it was is rewritten too.
|
|
71
|
+
*/
|
|
72
|
+
readonly shouldOverwriteEditedReleases: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Whether the GitHub release of each rewritten section is rewritten too.
|
|
75
|
+
*/
|
|
76
|
+
readonly shouldRewriteReleases: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Whether anything is changed. Without it the command only reports.
|
|
79
|
+
*/
|
|
80
|
+
readonly shouldWrite: boolean;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Creates the command's outside world: commands run with `spawnSync`, files read and written with `node:fs`, the
|
|
84
|
+
* report written to stdout.
|
|
85
|
+
*
|
|
86
|
+
* @returns The dependencies.
|
|
87
|
+
*/
|
|
88
|
+
export declare function createNodeRewriteChangelogDependencies(): RewriteChangelogDependencies;
|
|
89
|
+
/**
|
|
90
|
+
* Builds the command's options from the command line: `--write` applies the changes, `--releases` adds the GitHub
|
|
91
|
+
* releases to them, `--overwrite-edited-releases` includes the releases whose notes were edited after publishing, and
|
|
92
|
+
* `--path=<file>` names the changelog (`CHANGELOG.md` by default).
|
|
93
|
+
*
|
|
94
|
+
* @param cliArguments - The arguments after the command name.
|
|
95
|
+
* @returns The options.
|
|
96
|
+
*/
|
|
97
|
+
export declare function parseRewriteChangelogArguments(cliArguments: readonly string[]): RewriteChangelogOptions;
|
|
98
|
+
/**
|
|
99
|
+
* Runs the `rewrite-changelog` command in the working directory, which is the repository root.
|
|
100
|
+
*
|
|
101
|
+
* @param cliArguments - The arguments after the command name.
|
|
102
|
+
* @param dependencies - The outside world. The real one when omitted.
|
|
103
|
+
* @returns The exit code: `1` when the arguments are wrong, git cannot be read or a release edit failed, `0` otherwise.
|
|
104
|
+
*/
|
|
105
|
+
export declare function runRewriteChangelogCli(cliArguments: readonly string[], dependencies?: RewriteChangelogDependencies): Promise<number>;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/*
|
|
2
|
+
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
|
3
|
+
if you want to view the source, please visit the github repository of this plugin
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { spawnSync } from "node:child_process";
|
|
7
|
+
import {
|
|
8
|
+
readFileSync,
|
|
9
|
+
writeFileSync
|
|
10
|
+
} from "node:fs";
|
|
11
|
+
import process from "node:process";
|
|
12
|
+
import {
|
|
13
|
+
rewriteChangelog,
|
|
14
|
+
rewriteReleaseNotes
|
|
15
|
+
} from "./changelog-rewrite.mjs";
|
|
16
|
+
const DEFAULT_CHANGELOG_PATH = "CHANGELOG.md";
|
|
17
|
+
const KNOWN_ARGUMENTS = ["--write", "--releases", "--overwrite-edited-releases", "--path="];
|
|
18
|
+
function createNodeRewriteChangelogDependencies() {
|
|
19
|
+
return {
|
|
20
|
+
exec(file, arguments_, input) {
|
|
21
|
+
return toResult(spawnSync(file, arguments_, { encoding: "utf-8", input, maxBuffer: Number.MAX_SAFE_INTEGER }));
|
|
22
|
+
},
|
|
23
|
+
log(text) {
|
|
24
|
+
process.stdout.write(`${text}
|
|
25
|
+
`);
|
|
26
|
+
},
|
|
27
|
+
readFile(path) {
|
|
28
|
+
return readFileSync(path, "utf-8");
|
|
29
|
+
},
|
|
30
|
+
writeFile(path, content) {
|
|
31
|
+
writeFileSync(path, content, "utf-8");
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function parseRewriteChangelogArguments(cliArguments) {
|
|
36
|
+
const unknown = cliArguments.filter((argument) => KNOWN_ARGUMENTS.every((known) => !(known.endsWith("=") ? argument.startsWith(known) : argument === known)));
|
|
37
|
+
if (unknown.length > 0) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
`rewrite-changelog: unknown argument ${unknown.map((argument) => `"${argument}"`).join(", ")}. Known: ${KNOWN_ARGUMENTS.join(", ")}.`
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
const path = cliArguments.find((argument) => argument.startsWith("--path="))?.slice("--path=".length);
|
|
43
|
+
return {
|
|
44
|
+
changelogPath: path === void 0 || path === "" ? DEFAULT_CHANGELOG_PATH : path,
|
|
45
|
+
shouldOverwriteEditedReleases: cliArguments.includes("--overwrite-edited-releases"),
|
|
46
|
+
shouldRewriteReleases: cliArguments.includes("--releases"),
|
|
47
|
+
shouldWrite: cliArguments.includes("--write")
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
async function runRewriteChangelogCli(cliArguments, dependencies = createNodeRewriteChangelogDependencies()) {
|
|
51
|
+
try {
|
|
52
|
+
return await runRewriteChangelog(parseRewriteChangelogArguments(cliArguments), dependencies);
|
|
53
|
+
} catch (error) {
|
|
54
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}
|
|
55
|
+
`);
|
|
56
|
+
return 1;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function execOrThrow(dependencies, file, arguments_) {
|
|
60
|
+
const result = dependencies.exec(file, arguments_);
|
|
61
|
+
if (result.exitCode !== 0) {
|
|
62
|
+
throw new Error(`rewrite-changelog: ${file} ${arguments_.join(" ")} failed: ${result.stderr.trim()}`);
|
|
63
|
+
}
|
|
64
|
+
return result.stdout;
|
|
65
|
+
}
|
|
66
|
+
function readReleaseNotes(dependencies) {
|
|
67
|
+
const output = execOrThrow(dependencies, "gh", [
|
|
68
|
+
"api",
|
|
69
|
+
"--paginate",
|
|
70
|
+
"repos/{owner}/{repo}/releases?per_page=100",
|
|
71
|
+
"--jq",
|
|
72
|
+
'.[] | {tag: .tag_name, body: (.body // "")}'
|
|
73
|
+
]);
|
|
74
|
+
const notesByTag = /* @__PURE__ */ new Map();
|
|
75
|
+
for (const line of output.split(/\r?\n/)) {
|
|
76
|
+
if (line.trim() === "") {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const release = JSON.parse(line);
|
|
80
|
+
notesByTag.set(release.tag, release.body);
|
|
81
|
+
}
|
|
82
|
+
return notesByTag;
|
|
83
|
+
}
|
|
84
|
+
function rewriteRelease(section, releaseNotes, options, dependencies) {
|
|
85
|
+
if (releaseNotes === void 0) {
|
|
86
|
+
dependencies.log(`release ${section.tag}: left alone, the repository has no GitHub release for it`);
|
|
87
|
+
return "ok";
|
|
88
|
+
}
|
|
89
|
+
const notes = rewriteReleaseNotes(releaseNotes, section, options.shouldOverwriteEditedReleases);
|
|
90
|
+
if (notes === null) {
|
|
91
|
+
dependencies.log(`release ${section.tag}: left alone, its notes are not the changelog section as it was (--overwrite-edited-releases rewrites it)`);
|
|
92
|
+
return "ok";
|
|
93
|
+
}
|
|
94
|
+
if (!options.shouldWrite) {
|
|
95
|
+
dependencies.log(`release ${section.tag}: would be rewritten`);
|
|
96
|
+
return "ok";
|
|
97
|
+
}
|
|
98
|
+
const edit = dependencies.exec("gh", ["release", "edit", section.tag, "--notes-file", "-"], notes);
|
|
99
|
+
if (edit.exitCode !== 0) {
|
|
100
|
+
dependencies.log(`release ${section.tag}: the edit FAILED: ${edit.stderr.trim()}`);
|
|
101
|
+
return "failed";
|
|
102
|
+
}
|
|
103
|
+
dependencies.log(`release ${section.tag}: rewritten`);
|
|
104
|
+
return "ok";
|
|
105
|
+
}
|
|
106
|
+
async function runRewriteChangelog(options, dependencies) {
|
|
107
|
+
const changelog = dependencies.readFile(options.changelogPath);
|
|
108
|
+
const tags = execOrThrow(dependencies, "git", ["tag", "--list"]).split(/\r?\n/).filter(Boolean);
|
|
109
|
+
const result = await rewriteChangelog(changelog, {
|
|
110
|
+
getCommitMessages: (fromTag, toTag) => Promise.resolve(
|
|
111
|
+
execOrThrow(dependencies, "git", ["log", "--format=%B", "--first-parent", "-z", fromTag === void 0 ? toTag : `${fromTag}..${toTag}`]).split("\0").filter((message) => message.trim() !== "")
|
|
112
|
+
),
|
|
113
|
+
tags
|
|
114
|
+
});
|
|
115
|
+
for (const section of result.rewritten) {
|
|
116
|
+
const tagNote = section.tag === void 0 ? ", no tag, so grouped from the bullets alone" : "";
|
|
117
|
+
dependencies.log(`${section.version}: rewritten, ${String(section.matchedCount)} of ${String(section.oldBody.split("\n").length)} bullets matched to commits${tagNote}`);
|
|
118
|
+
}
|
|
119
|
+
for (const section of result.kept) {
|
|
120
|
+
dependencies.log(`${section.version}: kept, ${section.reason}`);
|
|
121
|
+
}
|
|
122
|
+
if (options.shouldWrite) {
|
|
123
|
+
dependencies.writeFile(options.changelogPath, result.content);
|
|
124
|
+
dependencies.log(`${options.changelogPath}: written`);
|
|
125
|
+
} else {
|
|
126
|
+
dependencies.log(`${options.changelogPath}: dry run, nothing written (pass --write to apply)`);
|
|
127
|
+
}
|
|
128
|
+
let isSuccess = true;
|
|
129
|
+
if (options.shouldRewriteReleases) {
|
|
130
|
+
const notesByTag = readReleaseNotes(dependencies);
|
|
131
|
+
for (const section of result.rewritten) {
|
|
132
|
+
if (section.tag !== void 0) {
|
|
133
|
+
isSuccess = rewriteRelease({ ...section, tag: section.tag }, notesByTag.get(section.tag), options, dependencies) === "ok" && isSuccess;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return isSuccess ? 0 : 1;
|
|
138
|
+
}
|
|
139
|
+
function toResult(result) {
|
|
140
|
+
return result.error ? { exitCode: 1, stderr: result.error.message, stdout: "" } : { exitCode: result.status ?? 1, stderr: result.stderr, stdout: result.stdout };
|
|
141
|
+
}
|
|
142
|
+
export {
|
|
143
|
+
createNodeRewriteChangelogDependencies,
|
|
144
|
+
parseRewriteChangelogArguments,
|
|
145
|
+
runRewriteChangelogCli
|
|
146
|
+
};
|
|
147
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2NoYW5nZWxvZy1yZXdyaXRlLWNsaS50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIFRoZSBgcmV3cml0ZS1jaGFuZ2Vsb2dgIGNvbW1hbmQ6IHJld3JpdGVzIGEgcHJvamVjdCdzIHB1Ymxpc2hlZCBgQ0hBTkdFTE9HLm1kYCBzZWN0aW9ucywgYW5kIG9wdGlvbmFsbHkgaXRzIEdpdEh1YlxuICogcmVsZWFzZSBub3RlcywgaW50byB0aGUgYGdyb3VwZWRgIGxheW91dCwgYnkgd2lyaW5nIHtAbGluayByZXdyaXRlQ2hhbmdlbG9nfSB0byB0aGUgcmVhbCBnaXQsIGBnaGAgYW5kIGZpbGUgc3lzdGVtLlxuICpcbiAqIEl0IGNoYW5nZXMgbm90aGluZyB1bmxlc3MgYC0td3JpdGVgIGlzIHBhc3NlZCwgc28gdGhlIGZpcnN0IHJ1biBpcyBhbHdheXMgYSByZXBvcnQgb2Ygd2hhdCBpdCB3b3VsZCBkby5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7IFNwYXduU3luY1JldHVybnMgfSBmcm9tICdub2RlOmNoaWxkX3Byb2Nlc3MnO1xuXG5pbXBvcnQgeyBzcGF3blN5bmMgfSBmcm9tICdub2RlOmNoaWxkX3Byb2Nlc3MnO1xuaW1wb3J0IHtcbiAgcmVhZEZpbGVTeW5jLFxuICB3cml0ZUZpbGVTeW5jXG59IGZyb20gJ25vZGU6ZnMnO1xuaW1wb3J0IHByb2Nlc3MgZnJvbSAnbm9kZTpwcm9jZXNzJztcblxuaW1wb3J0IHR5cGUgeyBSZXdyaXR0ZW5DaGFuZ2Vsb2dTZWN0aW9uIH0gZnJvbSAnLi9jaGFuZ2Vsb2ctcmV3cml0ZS50cyc7XG5cbmltcG9ydCB7XG4gIHJld3JpdGVDaGFuZ2Vsb2csXG4gIHJld3JpdGVSZWxlYXNlTm90ZXNcbn0gZnJvbSAnLi9jaGFuZ2Vsb2ctcmV3cml0ZS50cyc7XG5cbi8qKlxuICogVGhlIHJlc3VsdCBvZiBvbmUgY29tbWFuZCB0aGUgYHJld3JpdGUtY2hhbmdlbG9nYCBjb21tYW5kIHJ1bnMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmV3cml0ZUNoYW5nZWxvZ0NvbW1hbmRSZXN1bHQge1xuICAvKipcbiAgICogVGhlIGV4aXQgY29kZS5cbiAgICovXG4gIHJlYWRvbmx5IGV4aXRDb2RlOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRoZSBzdGFuZGFyZCBlcnJvci5cbiAgICovXG4gIHJlYWRvbmx5IHN0ZGVycjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgc3RhbmRhcmQgb3V0cHV0LlxuICAgKi9cbiAgcmVhZG9ubHkgc3Rkb3V0OiBzdHJpbmc7XG59XG5cbi8qKlxuICogVGhlIG91dHNpZGUgd29ybGQgb2YgdGhlIGByZXdyaXRlLWNoYW5nZWxvZ2AgY29tbWFuZC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZXdyaXRlQ2hhbmdlbG9nRGVwZW5kZW5jaWVzIHtcbiAgLyoqXG4gICAqIFJ1bnMgYSBjb21tYW5kIGluIHRoZSB3b3JraW5nIGRpcmVjdG9yeS5cbiAgICpcbiAgICogQHBhcmFtIGZpbGUgLSBUaGUgZXhlY3V0YWJsZS5cbiAgICogQHBhcmFtIGFyZ3VtZW50c18gLSBJdHMgYXJndW1lbnRzLlxuICAgKiBAcGFyYW0gaW5wdXQgLSBXaGF0IHRvIHdyaXRlIHRvIGl0cyBzdGFuZGFyZCBpbnB1dC5cbiAgICogQHJldHVybnMgVGhlIHJlc3VsdC5cbiAgICovXG4gIHJlYWRvbmx5IGV4ZWM6IChmaWxlOiBzdHJpbmcsIGFyZ3VtZW50c186IHJlYWRvbmx5IHN0cmluZ1tdLCBpbnB1dD86IHN0cmluZykgPT4gUmV3cml0ZUNoYW5nZWxvZ0NvbW1hbmRSZXN1bHQ7XG5cbiAgLyoqXG4gICAqIFdyaXRlcyBvbmUgbGluZSBvZiB0aGUgcmVwb3J0LlxuICAgKlxuICAgKiBAcGFyYW0gdGV4dCAtIFRoZSBsaW5lLlxuICAgKi9cbiAgcmVhZG9ubHkgbG9nOiAodGV4dDogc3RyaW5nKSA9PiB2b2lkO1xuXG4gIC8qKlxuICAgKiBSZWFkcyBhIHRleHQgZmlsZS5cbiAgICpcbiAgICogQHBhcmFtIHBhdGggLSBUaGUgcGF0aC5cbiAgICogQHJldHVybnMgVGhlIGNvbnRlbnQuXG4gICAqL1xuICByZWFkb25seSByZWFkRmlsZTogKHBhdGg6IHN0cmluZykgPT4gc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXcml0ZXMgYSB0ZXh0IGZpbGUuXG4gICAqXG4gICAqIEBwYXJhbSBwYXRoIC0gVGhlIHBhdGguXG4gICAqIEBwYXJhbSBjb250ZW50IC0gVGhlIGNvbnRlbnQuXG4gICAqL1xuICByZWFkb25seSB3cml0ZUZpbGU6IChwYXRoOiBzdHJpbmcsIGNvbnRlbnQ6IHN0cmluZykgPT4gdm9pZDtcbn1cblxuLyoqXG4gKiBUaGUgb3B0aW9ucyBvZiB0aGUgYHJld3JpdGUtY2hhbmdlbG9nYCBjb21tYW5kLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJld3JpdGVDaGFuZ2Vsb2dPcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSBgQ0hBTkdFTE9HLm1kYCB0byByZXdyaXRlLlxuICAgKi9cbiAgcmVhZG9ubHkgY2hhbmdlbG9nUGF0aDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIGEgR2l0SHViIHJlbGVhc2Ugd2hvc2Ugbm90ZXMgYXJlIG5vIGxvbmdlciBpdHMgY2hhbmdlbG9nIHNlY3Rpb24gYXMgaXQgd2FzIGlzIHJld3JpdHRlbiB0b28uXG4gICAqL1xuICByZWFkb25seSBzaG91bGRPdmVyd3JpdGVFZGl0ZWRSZWxlYXNlczogYm9vbGVhbjtcblxuICAvKipcbiAgICogV2hldGhlciB0aGUgR2l0SHViIHJlbGVhc2Ugb2YgZWFjaCByZXdyaXR0ZW4gc2VjdGlvbiBpcyByZXdyaXR0ZW4gdG9vLlxuICAgKi9cbiAgcmVhZG9ubHkgc2hvdWxkUmV3cml0ZVJlbGVhc2VzOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIGFueXRoaW5nIGlzIGNoYW5nZWQuIFdpdGhvdXQgaXQgdGhlIGNvbW1hbmQgb25seSByZXBvcnRzLlxuICAgKi9cbiAgcmVhZG9ubHkgc2hvdWxkV3JpdGU6IGJvb2xlYW47XG59XG5cbmludGVyZmFjZSBSZWxlYXNlUmVjb3JkIHtcbiAgcmVhZG9ubHkgYm9keTogc3RyaW5nO1xuICByZWFkb25seSB0YWc6IHN0cmluZztcbn1cblxudHlwZSBSZWxlYXNlUmV3cml0ZU91dGNvbWUgPSAnZmFpbGVkJyB8ICdvayc7XG5cbmludGVyZmFjZSBUYWdnZWRSZXdyaXR0ZW5TZWN0aW9uIGV4dGVuZHMgUmV3cml0dGVuQ2hhbmdlbG9nU2VjdGlvbiB7XG4gIHJlYWRvbmx5IHRhZzogc3RyaW5nO1xufVxuXG5jb25zdCBERUZBVUxUX0NIQU5HRUxPR19QQVRIID0gJ0NIQU5HRUxPRy5tZCc7XG5cbmNvbnN0IEtOT1dOX0FSR1VNRU5UUyA9IFsnLS13cml0ZScsICctLXJlbGVhc2VzJywgJy0tb3ZlcndyaXRlLWVkaXRlZC1yZWxlYXNlcycsICctLXBhdGg9J107XG5cbi8qKlxuICogQ3JlYXRlcyB0aGUgY29tbWFuZCdzIG91dHNpZGUgd29ybGQ6IGNvbW1hbmRzIHJ1biB3aXRoIGBzcGF3blN5bmNgLCBmaWxlcyByZWFkIGFuZCB3cml0dGVuIHdpdGggYG5vZGU6ZnNgLCB0aGVcbiAqIHJlcG9ydCB3cml0dGVuIHRvIHN0ZG91dC5cbiAqXG4gKiBAcmV0dXJucyBUaGUgZGVwZW5kZW5jaWVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlTm9kZVJld3JpdGVDaGFuZ2Vsb2dEZXBlbmRlbmNpZXMoKTogUmV3cml0ZUNoYW5nZWxvZ0RlcGVuZGVuY2llcyB7XG4gIHJldHVybiB7XG4gICAgZXhlYyhmaWxlLCBhcmd1bWVudHNfLCBpbnB1dCk6IFJld3JpdGVDaGFuZ2Vsb2dDb21tYW5kUmVzdWx0IHtcbiAgICAgIHJldHVybiB0b1Jlc3VsdChzcGF3blN5bmMoZmlsZSwgYXJndW1lbnRzXywgeyBlbmNvZGluZzogJ3V0Zi04JywgaW5wdXQsIG1heEJ1ZmZlcjogTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIgfSkpO1xuICAgIH0sXG4gICAgbG9nKHRleHQpOiB2b2lkIHtcbiAgICAgIHByb2Nlc3Muc3Rkb3V0LndyaXRlKGAke3RleHR9XFxuYCk7XG4gICAgfSxcbiAgICByZWFkRmlsZShwYXRoKTogc3RyaW5nIHtcbiAgICAgIHJldHVybiByZWFkRmlsZVN5bmMocGF0aCwgJ3V0Zi04Jyk7XG4gICAgfSxcbiAgICB3cml0ZUZpbGUocGF0aCwgY29udGVudCk6IHZvaWQge1xuICAgICAgd3JpdGVGaWxlU3luYyhwYXRoLCBjb250ZW50LCAndXRmLTgnKTtcbiAgICB9XG4gIH07XG59XG5cbi8qKlxuICogQnVpbGRzIHRoZSBjb21tYW5kJ3Mgb3B0aW9ucyBmcm9tIHRoZSBjb21tYW5kIGxpbmU6IGAtLXdyaXRlYCBhcHBsaWVzIHRoZSBjaGFuZ2VzLCBgLS1yZWxlYXNlc2AgYWRkcyB0aGUgR2l0SHViXG4gKiByZWxlYXNlcyB0byB0aGVtLCBgLS1vdmVyd3JpdGUtZWRpdGVkLXJlbGVhc2VzYCBpbmNsdWRlcyB0aGUgcmVsZWFzZXMgd2hvc2Ugbm90ZXMgd2VyZSBlZGl0ZWQgYWZ0ZXIgcHVibGlzaGluZywgYW5kXG4gKiBgLS1wYXRoPTxmaWxlPmAgbmFtZXMgdGhlIGNoYW5nZWxvZyAoYENIQU5HRUxPRy5tZGAgYnkgZGVmYXVsdCkuXG4gKlxuICogQHBhcmFtIGNsaUFyZ3VtZW50cyAtIFRoZSBhcmd1bWVudHMgYWZ0ZXIgdGhlIGNvbW1hbmQgbmFtZS5cbiAqIEByZXR1cm5zIFRoZSBvcHRpb25zLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VSZXdyaXRlQ2hhbmdlbG9nQXJndW1lbnRzKGNsaUFyZ3VtZW50czogcmVhZG9ubHkgc3RyaW5nW10pOiBSZXdyaXRlQ2hhbmdlbG9nT3B0aW9ucyB7XG4gIGNvbnN0IHVua25vd24gPSBjbGlBcmd1bWVudHMuZmlsdGVyKChhcmd1bWVudCkgPT4gS05PV05fQVJHVU1FTlRTLmV2ZXJ5KChrbm93bikgPT4gIShrbm93bi5lbmRzV2l0aCgnPScpID8gYXJndW1lbnQuc3RhcnRzV2l0aChrbm93bikgOiBhcmd1bWVudCA9PT0ga25vd24pKSk7XG4gIGlmICh1bmtub3duLmxlbmd0aCA+IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgcmV3cml0ZS1jaGFuZ2Vsb2c6IHVua25vd24gYXJndW1lbnQgJHt1bmtub3duLm1hcCgoYXJndW1lbnQpID0+IGBcIiR7YXJndW1lbnR9XCJgKS5qb2luKCcsICcpfS4gS25vd246ICR7S05PV05fQVJHVU1FTlRTLmpvaW4oJywgJyl9LmBcbiAgICApO1xuICB9XG5cbiAgY29uc3QgcGF0aCA9IGNsaUFyZ3VtZW50cy5maW5kKChhcmd1bWVudCkgPT4gYXJndW1lbnQuc3RhcnRzV2l0aCgnLS1wYXRoPScpKT8uc2xpY2UoJy0tcGF0aD0nLmxlbmd0aCk7XG4gIHJldHVybiB7XG4gICAgY2hhbmdlbG9nUGF0aDogcGF0aCA9PT0gdW5kZWZpbmVkIHx8IHBhdGggPT09ICcnID8gREVGQVVMVF9DSEFOR0VMT0dfUEFUSCA6IHBhdGgsXG4gICAgc2hvdWxkT3ZlcndyaXRlRWRpdGVkUmVsZWFzZXM6IGNsaUFyZ3VtZW50cy5pbmNsdWRlcygnLS1vdmVyd3JpdGUtZWRpdGVkLXJlbGVhc2VzJyksXG4gICAgc2hvdWxkUmV3cml0ZVJlbGVhc2VzOiBjbGlBcmd1bWVudHMuaW5jbHVkZXMoJy0tcmVsZWFzZXMnKSxcbiAgICBzaG91bGRXcml0ZTogY2xpQXJndW1lbnRzLmluY2x1ZGVzKCctLXdyaXRlJylcbiAgfTtcbn1cblxuLyoqXG4gKiBSdW5zIHRoZSBgcmV3cml0ZS1jaGFuZ2Vsb2dgIGNvbW1hbmQgaW4gdGhlIHdvcmtpbmcgZGlyZWN0b3J5LCB3aGljaCBpcyB0aGUgcmVwb3NpdG9yeSByb290LlxuICpcbiAqIEBwYXJhbSBjbGlBcmd1bWVudHMgLSBUaGUgYXJndW1lbnRzIGFmdGVyIHRoZSBjb21tYW5kIG5hbWUuXG4gKiBAcGFyYW0gZGVwZW5kZW5jaWVzIC0gVGhlIG91dHNpZGUgd29ybGQuIFRoZSByZWFsIG9uZSB3aGVuIG9taXR0ZWQuXG4gKiBAcmV0dXJucyBUaGUgZXhpdCBjb2RlOiBgMWAgd2hlbiB0aGUgYXJndW1lbnRzIGFyZSB3cm9uZywgZ2l0IGNhbm5vdCBiZSByZWFkIG9yIGEgcmVsZWFzZSBlZGl0IGZhaWxlZCwgYDBgIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJ1blJld3JpdGVDaGFuZ2Vsb2dDbGkoXG4gIGNsaUFyZ3VtZW50czogcmVhZG9ubHkgc3RyaW5nW10sXG4gIGRlcGVuZGVuY2llczogUmV3cml0ZUNoYW5nZWxvZ0RlcGVuZGVuY2llcyA9IGNyZWF0ZU5vZGVSZXdyaXRlQ2hhbmdlbG9nRGVwZW5kZW5jaWVzKClcbik6IFByb21pc2U8bnVtYmVyPiB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGF3YWl0IHJ1blJld3JpdGVDaGFuZ2Vsb2cocGFyc2VSZXdyaXRlQ2hhbmdlbG9nQXJndW1lbnRzKGNsaUFyZ3VtZW50cyksIGRlcGVuZGVuY2llcyk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgLy8gQSB3cm9uZyBhcmd1bWVudCBvciBhbiB1bnJlYWRhYmxlIHJlcG9zaXRvcnkgaXMgdGhlIHVzZXIncyB0byBmaXgsIHNvIGl0IGdldHMgaXRzIG1lc3NhZ2UgcmF0aGVyIHRoYW4gYSBzdGFjayB0cmFjZS5cbiAgICBwcm9jZXNzLnN0ZGVyci53cml0ZShgJHtlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcil9XFxuYCk7XG4gICAgcmV0dXJuIDE7XG4gIH1cbn1cblxuZnVuY3Rpb24gZXhlY09yVGhyb3coZGVwZW5kZW5jaWVzOiBSZXdyaXRlQ2hhbmdlbG9nRGVwZW5kZW5jaWVzLCBmaWxlOiBzdHJpbmcsIGFyZ3VtZW50c186IHJlYWRvbmx5IHN0cmluZ1tdKTogc3RyaW5nIHtcbiAgY29uc3QgcmVzdWx0ID0gZGVwZW5kZW5jaWVzLmV4ZWMoZmlsZSwgYXJndW1lbnRzXyk7XG4gIGlmIChyZXN1bHQuZXhpdENvZGUgIT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYHJld3JpdGUtY2hhbmdlbG9nOiAke2ZpbGV9ICR7YXJndW1lbnRzXy5qb2luKCcgJyl9IGZhaWxlZDogJHtyZXN1bHQuc3RkZXJyLnRyaW0oKX1gKTtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQuc3Rkb3V0O1xufVxuXG4vKipcbiAqIFJlYWRzIHRoZSBub3RlcyBvZiBldmVyeSBHaXRIdWIgcmVsZWFzZSBvZiB0aGUgcmVwb3NpdG9yeSBpbiBvbmUgcGFnaW5hdGVkIGNhbGwsIHNpbmNlIG9uZSBgZ2ggcmVsZWFzZSB2aWV3YCBwZXJcbiAqIHJlbGVhc2UgdGFrZXMgbWludXRlcyBvbiBhIHByb2plY3Qgd2l0aCBodW5kcmVkcyBvZiB0aGVtLlxuICpcbiAqIEBwYXJhbSBkZXBlbmRlbmNpZXMgLSBUaGUgb3V0c2lkZSB3b3JsZC5cbiAqIEByZXR1cm5zIFRoZSBub3RlcywgYnkgdGFnLlxuICovXG5mdW5jdGlvbiByZWFkUmVsZWFzZU5vdGVzKGRlcGVuZGVuY2llczogUmV3cml0ZUNoYW5nZWxvZ0RlcGVuZGVuY2llcyk6IE1hcDxzdHJpbmcsIHN0cmluZz4ge1xuICBjb25zdCBvdXRwdXQgPSBleGVjT3JUaHJvdyhkZXBlbmRlbmNpZXMsICdnaCcsIFtcbiAgICAnYXBpJyxcbiAgICAnLS1wYWdpbmF0ZScsXG4gICAgJ3JlcG9zL3tvd25lcn0ve3JlcG99L3JlbGVhc2VzP3Blcl9wYWdlPTEwMCcsXG4gICAgJy0tanEnLFxuICAgICcuW10gfCB7dGFnOiAudGFnX25hbWUsIGJvZHk6ICguYm9keSAvLyBcIlwiKX0nXG4gIF0pO1xuICBjb25zdCBub3Rlc0J5VGFnID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oKTtcbiAgZm9yIChjb25zdCBsaW5lIG9mIG91dHB1dC5zcGxpdCgvXFxyP1xcbi8pKSB7XG4gICAgaWYgKGxpbmUudHJpbSgpID09PSAnJykge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgY29uc3QgcmVsZWFzZSA9IEpTT04ucGFyc2UobGluZSkgYXMgUmVsZWFzZVJlY29yZDtcbiAgICBub3Rlc0J5VGFnLnNldChyZWxlYXNlLnRhZywgcmVsZWFzZS5ib2R5KTtcbiAgfVxuXG4gIHJldHVybiBub3Rlc0J5VGFnO1xufVxuXG5mdW5jdGlvbiByZXdyaXRlUmVsZWFzZShcbiAgc2VjdGlvbjogVGFnZ2VkUmV3cml0dGVuU2VjdGlvbixcbiAgcmVsZWFzZU5vdGVzOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gIG9wdGlvbnM6IFJld3JpdGVDaGFuZ2Vsb2dPcHRpb25zLFxuICBkZXBlbmRlbmNpZXM6IFJld3JpdGVDaGFuZ2Vsb2dEZXBlbmRlbmNpZXNcbik6IFJlbGVhc2VSZXdyaXRlT3V0Y29tZSB7XG4gIGlmIChyZWxlYXNlTm90ZXMgPT09IHVuZGVmaW5lZCkge1xuICAgIGRlcGVuZGVuY2llcy5sb2coYHJlbGVhc2UgJHtzZWN0aW9uLnRhZ306IGxlZnQgYWxvbmUsIHRoZSByZXBvc2l0b3J5IGhhcyBubyBHaXRIdWIgcmVsZWFzZSBmb3IgaXRgKTtcbiAgICByZXR1cm4gJ29rJztcbiAgfVxuXG4gIGNvbnN0IG5vdGVzID0gcmV3cml0ZVJlbGVhc2VOb3RlcyhyZWxlYXNlTm90ZXMsIHNlY3Rpb24sIG9wdGlvbnMuc2hvdWxkT3ZlcndyaXRlRWRpdGVkUmVsZWFzZXMpO1xuICBpZiAobm90ZXMgPT09IG51bGwpIHtcbiAgICBkZXBlbmRlbmNpZXMubG9nKGByZWxlYXNlICR7c2VjdGlvbi50YWd9OiBsZWZ0IGFsb25lLCBpdHMgbm90ZXMgYXJlIG5vdCB0aGUgY2hhbmdlbG9nIHNlY3Rpb24gYXMgaXQgd2FzICgtLW92ZXJ3cml0ZS1lZGl0ZWQtcmVsZWFzZXMgcmV3cml0ZXMgaXQpYCk7XG4gICAgcmV0dXJuICdvayc7XG4gIH1cblxuICBpZiAoIW9wdGlvbnMuc2hvdWxkV3JpdGUpIHtcbiAgICBkZXBlbmRlbmNpZXMubG9nKGByZWxlYXNlICR7c2VjdGlvbi50YWd9OiB3b3VsZCBiZSByZXdyaXR0ZW5gKTtcbiAgICByZXR1cm4gJ29rJztcbiAgfVxuXG4gIGNvbnN0IGVkaXQgPSBkZXBlbmRlbmNpZXMuZXhlYygnZ2gnLCBbJ3JlbGVhc2UnLCAnZWRpdCcsIHNlY3Rpb24udGFnLCAnLS1ub3Rlcy1maWxlJywgJy0nXSwgbm90ZXMpO1xuICBpZiAoZWRpdC5leGl0Q29kZSAhPT0gMCkge1xuICAgIGRlcGVuZGVuY2llcy5sb2coYHJlbGVhc2UgJHtzZWN0aW9uLnRhZ306IHRoZSBlZGl0IEZBSUxFRDogJHtlZGl0LnN0ZGVyci50cmltKCl9YCk7XG4gICAgcmV0dXJuICdmYWlsZWQnO1xuICB9XG5cbiAgZGVwZW5kZW5jaWVzLmxvZyhgcmVsZWFzZSAke3NlY3Rpb24udGFnfTogcmV3cml0dGVuYCk7XG4gIHJldHVybiAnb2snO1xufVxuXG5hc3luYyBmdW5jdGlvbiBydW5SZXdyaXRlQ2hhbmdlbG9nKG9wdGlvbnM6IFJld3JpdGVDaGFuZ2Vsb2dPcHRpb25zLCBkZXBlbmRlbmNpZXM6IFJld3JpdGVDaGFuZ2Vsb2dEZXBlbmRlbmNpZXMpOiBQcm9taXNlPG51bWJlcj4ge1xuICBjb25zdCBjaGFuZ2Vsb2cgPSBkZXBlbmRlbmNpZXMucmVhZEZpbGUob3B0aW9ucy5jaGFuZ2Vsb2dQYXRoKTtcbiAgY29uc3QgdGFncyA9IGV4ZWNPclRocm93KGRlcGVuZGVuY2llcywgJ2dpdCcsIFsndGFnJywgJy0tbGlzdCddKS5zcGxpdCgvXFxyP1xcbi8pLmZpbHRlcihCb29sZWFuKTtcbiAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcmV3cml0ZUNoYW5nZWxvZyhjaGFuZ2Vsb2csIHtcbiAgICBnZXRDb21taXRNZXNzYWdlczogKGZyb21UYWcsIHRvVGFnKSA9PlxuICAgICAgUHJvbWlzZS5yZXNvbHZlKFxuICAgICAgICBleGVjT3JUaHJvdyhkZXBlbmRlbmNpZXMsICdnaXQnLCBbJ2xvZycsICctLWZvcm1hdD0lQicsICctLWZpcnN0LXBhcmVudCcsICcteicsIGZyb21UYWcgPT09IHVuZGVmaW5lZCA/IHRvVGFnIDogYCR7ZnJvbVRhZ30uLiR7dG9UYWd9YF0pXG4gICAgICAgICAgLnNwbGl0KCdcXDAnKVxuICAgICAgICAgIC5maWx0ZXIoKG1lc3NhZ2UpID0+IG1lc3NhZ2UudHJpbSgpICE9PSAnJylcbiAgICAgICksXG4gICAgdGFnc1xuICB9KTtcblxuICBmb3IgKGNvbnN0IHNlY3Rpb24gb2YgcmVzdWx0LnJld3JpdHRlbikge1xuICAgIGNvbnN0IHRhZ05vdGUgPSBzZWN0aW9uLnRhZyA9PT0gdW5kZWZpbmVkID8gJywgbm8gdGFnLCBzbyBncm91cGVkIGZyb20gdGhlIGJ1bGxldHMgYWxvbmUnIDogJyc7XG4gICAgZGVwZW5kZW5jaWVzLmxvZyhgJHtzZWN0aW9uLnZlcnNpb259OiByZXdyaXR0ZW4sICR7U3RyaW5nKHNlY3Rpb24ubWF0Y2hlZENvdW50KX0gb2YgJHtTdHJpbmcoc2VjdGlvbi5vbGRCb2R5LnNwbGl0KCdcXG4nKS5sZW5ndGgpfSBidWxsZXRzIG1hdGNoZWQgdG8gY29tbWl0cyR7dGFnTm90ZX1gKTtcbiAgfVxuXG4gIGZvciAoY29uc3Qgc2VjdGlvbiBvZiByZXN1bHQua2VwdCkge1xuICAgIGRlcGVuZGVuY2llcy5sb2coYCR7c2VjdGlvbi52ZXJzaW9ufToga2VwdCwgJHtzZWN0aW9uLnJlYXNvbn1gKTtcbiAgfVxuXG4gIGlmIChvcHRpb25zLnNob3VsZFdyaXRlKSB7XG4gICAgZGVwZW5kZW5jaWVzLndyaXRlRmlsZShvcHRpb25zLmNoYW5nZWxvZ1BhdGgsIHJlc3VsdC5jb250ZW50KTtcbiAgICBkZXBlbmRlbmNpZXMubG9nKGAke29wdGlvbnMuY2hhbmdlbG9nUGF0aH06IHdyaXR0ZW5gKTtcbiAgfSBlbHNlIHtcbiAgICBkZXBlbmRlbmNpZXMubG9nKGAke29wdGlvbnMuY2hhbmdlbG9nUGF0aH06IGRyeSBydW4sIG5vdGhpbmcgd3JpdHRlbiAocGFzcyAtLXdyaXRlIHRvIGFwcGx5KWApO1xuICB9XG5cbiAgbGV0IGlzU3VjY2VzcyA9IHRydWU7XG4gIGlmIChvcHRpb25zLnNob3VsZFJld3JpdGVSZWxlYXNlcykge1xuICAgIGNvbnN0IG5vdGVzQnlUYWcgPSByZWFkUmVsZWFzZU5vdGVzKGRlcGVuZGVuY2llcyk7XG4gICAgZm9yIChjb25zdCBzZWN0aW9uIG9mIHJlc3VsdC5yZXdyaXR0ZW4pIHtcbiAgICAgIGlmIChzZWN0aW9uLnRhZyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGlzU3VjY2VzcyA9IHJld3JpdGVSZWxlYXNlKHsgLi4uc2VjdGlvbiwgdGFnOiBzZWN0aW9uLnRhZyB9LCBub3Rlc0J5VGFnLmdldChzZWN0aW9uLnRhZyksIG9wdGlvbnMsIGRlcGVuZGVuY2llcykgPT09ICdvaycgJiYgaXNTdWNjZXNzO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBpc1N1Y2Nlc3MgPyAwIDogMTtcbn1cblxuZnVuY3Rpb24gdG9SZXN1bHQocmVzdWx0OiBTcGF3blN5bmNSZXR1cm5zPHN0cmluZz4pOiBSZXdyaXRlQ2hhbmdlbG9nQ29tbWFuZFJlc3VsdCB7XG4gIHJldHVybiByZXN1bHQuZXJyb3JcbiAgICA/IHsgZXhpdENvZGU6IDEsIHN0ZGVycjogcmVzdWx0LmVycm9yLm1lc3NhZ2UsIHN0ZG91dDogJycgfVxuICAgIDogeyBleGl0Q29kZTogcmVzdWx0LnN0YXR1cyA/PyAxLCBzdGRlcnI6IHJlc3VsdC5zdGRlcnIsIHN0ZG91dDogcmVzdWx0LnN0ZG91dCB9O1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7QUFXQSxTQUFTLGlCQUFpQjtBQUMxQjtBQUFBLEVBQ0U7QUFBQSxFQUNBO0FBQUEsT0FDSztBQUNQLE9BQU8sYUFBYTtBQUlwQjtBQUFBLEVBQ0U7QUFBQSxFQUNBO0FBQUEsT0FDSztBQWdHUCxNQUFNLHlCQUF5QjtBQUUvQixNQUFNLGtCQUFrQixDQUFDLFdBQVcsY0FBYywrQkFBK0IsU0FBUztBQVFuRixTQUFTLHlDQUF1RTtBQUNyRixTQUFPO0FBQUEsSUFDTCxLQUFLLE1BQU0sWUFBWSxPQUFzQztBQUMz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
|