obsidian-integration-testing 15.0.0 → 17.0.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.
Files changed (73) hide show
  1. package/dist/lib/cjs/adb.cjs +2 -2
  2. package/dist/lib/cjs/adb.d.cts +10 -0
  3. package/dist/lib/cjs/avd-name-channel.cjs +74 -0
  4. package/dist/lib/cjs/avd-name-channel.d.cts +152 -0
  5. package/dist/lib/cjs/avd-probe-verdict.cjs +11 -4
  6. package/dist/lib/cjs/avd-probe-verdict.d.cts +7 -0
  7. package/dist/lib/cjs/device-screenshot.cjs +1 -1
  8. package/dist/lib/cjs/device-screenshot.d.cts +3 -1
  9. package/dist/lib/cjs/emulator-backend.cjs +22 -1
  10. package/dist/lib/cjs/emulator-backend.d.cts +81 -0
  11. package/dist/lib/cjs/emulator-reclaim.cjs +78 -34
  12. package/dist/lib/cjs/emulator-reclaim.d.cts +57 -9
  13. package/dist/lib/cjs/enable-plugin.cjs +17 -8
  14. package/dist/lib/cjs/enable-plugin.d.cts +3 -1
  15. package/dist/lib/cjs/host-process-query-verdict.cjs +103 -0
  16. package/dist/lib/cjs/host-process-query-verdict.d.cts +196 -0
  17. package/dist/lib/cjs/index.cjs +14 -1
  18. package/dist/lib/cjs/index.d.cts +3 -1
  19. package/dist/lib/cjs/label-screenshot.cjs +2 -2
  20. package/dist/lib/cjs/launched-device-selection.cjs +46 -0
  21. package/dist/lib/cjs/launched-device-selection.d.cts +112 -0
  22. package/dist/lib/cjs/library.cjs +1 -1
  23. package/dist/lib/cjs/paint-out-status-bar.cjs +170 -0
  24. package/dist/lib/cjs/paint-out-status-bar.d.cts +236 -0
  25. package/dist/lib/cjs/port-owner-query-verdict.cjs +94 -0
  26. package/dist/lib/cjs/port-owner-query-verdict.d.cts +161 -0
  27. package/dist/lib/cjs/resolve-emulator-device-id.cjs +27 -4
  28. package/dist/lib/cjs/sharp-loader.cjs +1 -1
  29. package/dist/lib/cjs/sharp-loader.d.cts +67 -2
  30. package/dist/lib/cjs/soft-keyboard-geometry.cjs +12 -2
  31. package/dist/lib/cjs/soft-keyboard-geometry.d.cts +17 -2
  32. package/dist/lib/cjs/soft-keyboard.cjs +130 -28
  33. package/dist/lib/cjs/soft-keyboard.d.cts +65 -6
  34. package/dist/lib/cjs/transport-appium.cjs +74 -4
  35. package/dist/lib/cjs/transport-appium.d.cts +49 -2
  36. package/dist/lib/cjs/transport-factory.cjs +162 -42
  37. package/dist/lib/esm/adb.d.mts +10 -0
  38. package/dist/lib/esm/adb.mjs +2 -2
  39. package/dist/lib/esm/avd-name-channel.d.mts +152 -0
  40. package/dist/lib/esm/avd-name-channel.mjs +45 -0
  41. package/dist/lib/esm/avd-probe-verdict.d.mts +7 -0
  42. package/dist/lib/esm/avd-probe-verdict.mjs +15 -4
  43. package/dist/lib/esm/device-screenshot.d.mts +3 -1
  44. package/dist/lib/esm/device-screenshot.mjs +1 -1
  45. package/dist/lib/esm/emulator-backend.d.mts +81 -0
  46. package/dist/lib/esm/emulator-backend.mjs +19 -1
  47. package/dist/lib/esm/emulator-reclaim.d.mts +57 -9
  48. package/dist/lib/esm/emulator-reclaim.mjs +84 -36
  49. package/dist/lib/esm/enable-plugin.d.mts +3 -1
  50. package/dist/lib/esm/enable-plugin.mjs +17 -8
  51. package/dist/lib/esm/host-process-query-verdict.d.mts +196 -0
  52. package/dist/lib/esm/host-process-query-verdict.mjs +74 -0
  53. package/dist/lib/esm/index.d.mts +3 -1
  54. package/dist/lib/esm/index.mjs +15 -1
  55. package/dist/lib/esm/label-screenshot.mjs +2 -2
  56. package/dist/lib/esm/launched-device-selection.d.mts +112 -0
  57. package/dist/lib/esm/launched-device-selection.mjs +21 -0
  58. package/dist/lib/esm/library.mjs +1 -1
  59. package/dist/lib/esm/paint-out-status-bar.d.mts +236 -0
  60. package/dist/lib/esm/paint-out-status-bar.mjs +142 -0
  61. package/dist/lib/esm/port-owner-query-verdict.d.mts +161 -0
  62. package/dist/lib/esm/port-owner-query-verdict.mjs +73 -0
  63. package/dist/lib/esm/resolve-emulator-device-id.mjs +32 -4
  64. package/dist/lib/esm/sharp-loader.d.mts +67 -2
  65. package/dist/lib/esm/sharp-loader.mjs +1 -1
  66. package/dist/lib/esm/soft-keyboard-geometry.d.mts +17 -2
  67. package/dist/lib/esm/soft-keyboard-geometry.mjs +11 -2
  68. package/dist/lib/esm/soft-keyboard.d.mts +65 -6
  69. package/dist/lib/esm/soft-keyboard.mjs +131 -28
  70. package/dist/lib/esm/transport-appium.d.mts +49 -2
  71. package/dist/lib/esm/transport-appium.mjs +74 -4
  72. package/dist/lib/esm/transport-factory.mjs +176 -44
  73. package/package.json +1 -1
@@ -0,0 +1,236 @@
1
+ /**
2
+ * @file
3
+ *
4
+ * Paints the device's status bar out of a captured frame, so a device capture
5
+ * can be committed.
6
+ *
7
+ * A framebuffer carries the status bar, and a status bar carries a wall clock, a
8
+ * battery that charges while the emulator runs and a radio that comes and goes.
9
+ * So re-running a capture suite on an unchanged tree rewrites its PNGs with
10
+ * content nobody can commit, and the churn is invisible until someone diffs two
11
+ * runs. `device-screenshot`'s header has always said a device capture is not
12
+ * byte-reproducible; this is what makes one.
13
+ *
14
+ * **Pinning the bar was tried first, and is NOT sufficient — that finding is the
15
+ * reason this helper exists rather than a `withSystemUiDemoMode` one.** SystemUI
16
+ * demo mode (`sysui_demo_allowed`, plus one `com.android.systemui.demo`
17
+ * broadcast per area: clock at a fixed `hhmm`, battery full and unplugged,
18
+ * radios hidden, notification icons off) held the clock at `12:00` and two runs
19
+ * still disagreed on **1823 full-contrast pixels**, because the bar's leading
20
+ * group is laid out at a different offset between emulator boots —
21
+ * intermittently, roughly one boot in four. The Tuner's `icon_blacklist` does
22
+ * not help either: demo mode draws its own icon layer and ignores it. Measured
23
+ * on a real AVD across five paired capture runs for `obsidian-link-picker`'s
24
+ * store frames, which is where this recipe was worked out before it moved here.
25
+ *
26
+ * Removing the band rather than pinning it also retires every device setting
27
+ * that pinning needed, and nothing in a status bar is evidence about a plugin. A
28
+ * listing frame without one is what a listing frame normally looks like.
29
+ *
30
+ * **The band's height is the caller's to measure, and there is deliberately no
31
+ * default.** A wrong height does not fail loudly by itself — it paints over the
32
+ * product. What stands between the two is {@link resolveStatusBarBand}: the row
33
+ * just under the bar's own content must be one flat color all the way across,
34
+ * which is what an empty band looks like and is also where the fill color is
35
+ * sampled from. A taller bar, or an Obsidian that draws higher, fails the
36
+ * capture instead.
37
+ *
38
+ * Compositing over a captured frame is not a new liberty: `labelScreenshot`
39
+ * already draws the caption band across the bottom of the same image.
40
+ */
41
+ /**
42
+ * Parameters for {@link buildStatusBarBandFailureMessage}.
43
+ */
44
+ export interface BuildStatusBarBandFailureMessageParams {
45
+ /**
46
+ * How far in from each edge the row was scanned, in pixels.
47
+ */
48
+ readonly edgeMarginInPixels: number;
49
+ /**
50
+ * The height of the band that was about to be painted, in pixels.
51
+ */
52
+ readonly heightInPixels: number;
53
+ /**
54
+ * The verdict being reported.
55
+ */
56
+ readonly verdict: StatusBarBandVerdict;
57
+ /**
58
+ * The frame's width, in pixels.
59
+ */
60
+ readonly widthInPixels: number;
61
+ }
62
+ /**
63
+ * Options for {@link paintOutStatusBar}.
64
+ */
65
+ export interface PaintOutStatusBarOptions {
66
+ /**
67
+ * How far in from each edge the clear-of-chrome check reads.
68
+ *
69
+ * @default {@link DEFAULT_STATUS_BAR_EDGE_MARGIN_IN_PIXELS}
70
+ */
71
+ readonly edgeMarginInPixels?: number;
72
+ /**
73
+ * How tall the device's status bar is, in framebuffer pixels.
74
+ *
75
+ * **Measured, never assumed, and deliberately without a default.** 24dp at a
76
+ * density of 320 is 48px, and that is one AVD's number rather than a constant
77
+ * of Android. Measure it on a frame: the bar's own content occupies the top
78
+ * rows, a few empty rows follow, and the app's top chrome starts at exactly
79
+ * this offset.
80
+ */
81
+ readonly heightInPixels: number;
82
+ /**
83
+ * How far above the band's bottom edge the fill color is sampled, in pixels.
84
+ *
85
+ * @default {@link DEFAULT_STATUS_BAR_SAMPLE_INSET_IN_PIXELS}
86
+ */
87
+ readonly sampleInsetInPixels?: number;
88
+ }
89
+ /**
90
+ * Parameters for {@link resolveStatusBarBand}.
91
+ */
92
+ export interface ResolveStatusBarBandParams {
93
+ /**
94
+ * How many bytes each pixel occupies in {@link ResolveStatusBarBandParams.pixels} — 3 for RGB, 4 for RGBA.
95
+ */
96
+ readonly channelCount: number;
97
+ /**
98
+ * How far in from each edge to start reading, in pixels.
99
+ *
100
+ * A device's rounded corners darken a handful of pixels at both ends of every
101
+ * row in the band, constantly and harmlessly; the check is about what the APP
102
+ * draws, so it ignores them.
103
+ *
104
+ * @default {@link DEFAULT_STATUS_BAR_EDGE_MARGIN_IN_PIXELS}
105
+ */
106
+ readonly edgeMarginInPixels?: number;
107
+ /**
108
+ * The height of the band, in pixels — the same number {@link paintOutStatusBar} would paint.
109
+ */
110
+ readonly heightInPixels: number;
111
+ /**
112
+ * The frame's raw pixels, row-major, as `sharp`'s `raw()` reports them.
113
+ */
114
+ readonly pixels: Uint8Array;
115
+ /**
116
+ * How far above the band's bottom edge the row is read from, in pixels.
117
+ *
118
+ * The bar's own content stops short of the band's bottom edge, so the rows
119
+ * immediately under it are empty; this picks one of them.
120
+ *
121
+ * @default {@link DEFAULT_STATUS_BAR_SAMPLE_INSET_IN_PIXELS}
122
+ */
123
+ readonly sampleInsetInPixels?: number;
124
+ /**
125
+ * The frame's width, in pixels.
126
+ */
127
+ readonly widthInPixels: number;
128
+ }
129
+ /**
130
+ * A color read out of a frame, channel by channel.
131
+ *
132
+ * This package's own type rather than `sharp`'s, because it is part of the
133
+ * public surface and `sharp` is an OPTIONAL peer: a consumer that never installs
134
+ * it still names this. Structurally what `sharp`'s `background` takes, which is
135
+ * how the fill block is created from one with no conversion in between.
136
+ */
137
+ export interface StatusBarBandColor {
138
+ /**
139
+ * The blue channel, 0-255.
140
+ */
141
+ readonly b: number;
142
+ /**
143
+ * The green channel, 0-255.
144
+ */
145
+ readonly g: number;
146
+ /**
147
+ * The red channel, 0-255.
148
+ */
149
+ readonly r: number;
150
+ }
151
+ /**
152
+ * What the row under the status bar's content turned out to hold.
153
+ *
154
+ * Verdict-as-data, like the compatibility and teardown checks: the reading and
155
+ * the throwing are separate, so a caller can ask what a frame looks like without
156
+ * having to catch an error to find out.
157
+ */
158
+ export interface StatusBarBandVerdict {
159
+ /**
160
+ * The color the band would be filled with — read from the first scanned column of the sample row.
161
+ */
162
+ readonly backgroundColor: StatusBarBandColor;
163
+ /**
164
+ * How many distinct colors the scanned row holds. One is what an empty band looks like.
165
+ */
166
+ readonly distinctColorCount: number;
167
+ /**
168
+ * The color at {@link StatusBarBandVerdict.firstDifferentColumnXInPixels}, or `null` when the row is flat.
169
+ */
170
+ readonly firstDifferentColor: null | StatusBarBandColor;
171
+ /**
172
+ * The first scanned column that differs from {@link StatusBarBandVerdict.backgroundColor}, or `null` when the row is flat.
173
+ */
174
+ readonly firstDifferentColumnXInPixels: null | number;
175
+ /**
176
+ * Whether the row is one flat color, and so whether the band holds nothing but device chrome.
177
+ */
178
+ readonly isClear: boolean;
179
+ /**
180
+ * Which row was read, as a distance from the top of the frame in pixels.
181
+ */
182
+ readonly sampleRowYInPixels: number;
183
+ }
184
+ /**
185
+ * How far in from each edge the clear-of-chrome check reads, in pixels.
186
+ *
187
+ * Exported because a caller tightening or loosening it wants to say so relative
188
+ * to this rather than in the abstract.
189
+ */
190
+ export declare const DEFAULT_STATUS_BAR_EDGE_MARGIN_IN_PIXELS = 100;
191
+ /**
192
+ * How far above the band's bottom edge the sample row sits, in pixels.
193
+ *
194
+ * Four rows up: far enough to clear the bar's own content, close enough to still
195
+ * be inside the band on every device this has been measured on.
196
+ */
197
+ export declare const DEFAULT_STATUS_BAR_SAMPLE_INSET_IN_PIXELS = 4;
198
+ /**
199
+ * Builds the message a band that is not clear is refused with.
200
+ *
201
+ * Separate from the throwing so it can be asserted on directly: what makes this
202
+ * failure actionable is the measurement, not the wording around it.
203
+ *
204
+ * @param params - The verdict and the geometry it was read with.
205
+ * @returns The message, ready to throw.
206
+ */
207
+ export declare function buildStatusBarBandFailureMessage(params: BuildStatusBarBandFailureMessageParams): string;
208
+ /**
209
+ * Fills the status-bar band with the background behind it, so the frame carries no device chrome.
210
+ *
211
+ * The image keeps its dimensions exactly: the band is composited OVER the frame,
212
+ * never cropped off it, because a store listing expects a specific size and a
213
+ * cropped frame is a different picture.
214
+ *
215
+ * @param bytes - The device framebuffer, as `captureDeviceScreenshot` returned it.
216
+ * @param options - How tall the band is, and how the check reads it.
217
+ * @returns A {@link Promise} that resolves to the same frame with the band painted out, as PNG bytes.
218
+ * @throws Error if `sharp` is not installed, the band is as tall as the frame or taller, or the row under
219
+ * the bar's content is not one flat color — see {@link buildStatusBarBandFailureMessage}.
220
+ */
221
+ export declare function paintOutStatusBar(bytes: Uint8Array, options: PaintOutStatusBarOptions): Promise<Uint8Array>;
222
+ /**
223
+ * Reads the row under the status bar's content and says whether the band is clear of the app.
224
+ *
225
+ * The band's height is a number a caller measured once, and a measured number
226
+ * can go stale — a taller status bar, or an Obsidian that draws higher, would
227
+ * have the capture quietly paint over the product. So the row just below the
228
+ * bar's own content is required to be one flat color all the way across: that
229
+ * is what an empty band looks like, and it is what the fill color is read from.
230
+ *
231
+ * @param params - The frame's raw pixels and the band's geometry.
232
+ * @returns What the scanned row holds.
233
+ * @throws Error if the geometry is degenerate — a non-positive dimension, a sample row above the top of
234
+ * the frame, a margin that leaves nothing to scan, or a buffer too short to hold the row.
235
+ */
236
+ export declare function resolveStatusBarBand(params: ResolveStatusBarBandParams): StatusBarBandVerdict;
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var port_owner_query_verdict_exports = {};
20
+ __export(port_owner_query_verdict_exports, {
21
+ buildPortOwnerQueryMessage: () => buildPortOwnerQueryMessage,
22
+ normalizeSyncExecError: () => normalizeSyncExecError,
23
+ resolvePortOwnerQueryOutcome: () => resolvePortOwnerQueryOutcome
24
+ });
25
+ module.exports = __toCommonJS(port_owner_query_verdict_exports);
26
+ var import_node_buffer = require("node:buffer");
27
+ var import_host_process_query_verdict = require("./host-process-query-verdict.cjs");
28
+ var import_type_guards = require("./type-guards.cjs");
29
+ const LSOF_NOTHING_FOUND_EXIT_CODE = 1;
30
+ function buildPortOwnerQueryMessage(params) {
31
+ const cost = `after ${(0, import_host_process_query_verdict.formatDuration)(params.elapsedInMilliseconds)}`;
32
+ const subject = `\`${params.command}\` (asking who listens on port ${String(params.port)})`;
33
+ const consequence = `Nothing is known about what still holds port ${String(params.port)}, so the escalation has no PID to kill \u2014 this is not the same as nothing holding it.`;
34
+ switch (params.outcome) {
35
+ case "answered": {
36
+ return void 0;
37
+ }
38
+ case "crashed": {
39
+ return `Warning: ${subject} died ${cost} without explaining itself (exit ${(0, import_host_process_query_verdict.formatExitCode)(params.exitCode)}, nothing on stderr). Suspect a crash or an interfering security product, and try the command by hand. ${consequence}`;
40
+ }
41
+ case "not-found": {
42
+ return `Warning: ${subject} could not be run at all ${cost}: the executable was not found on PATH. ${consequence}`;
43
+ }
44
+ case "output-overran": {
45
+ return `Warning: ${subject} produced more output ${cost} than the query's buffer allows, so none of it could be read. Raise the buffer. ${consequence}`;
46
+ }
47
+ case "refused": {
48
+ return `Warning: ${subject} refused the request ${cost} (exit ${(0, import_host_process_query_verdict.formatExitCode)(params.exitCode)}): ${(0, import_host_process_query_verdict.formatRefusal)(params.standardError)} ${consequence}`;
49
+ }
50
+ case "timed-out": {
51
+ return `Warning: ${subject} did not finish within its ${(0, import_host_process_query_verdict.formatDuration)(params.timeoutInMilliseconds)} budget and was killed ${cost}${params.signal === null ? "" : ` (${params.signal})`}. ${consequence}`;
52
+ }
53
+ default: {
54
+ return (0, import_type_guards.assertNever)(params.outcome);
55
+ }
56
+ }
57
+ }
58
+ function normalizeSyncExecError(error) {
59
+ const record = typeof error === "object" && error !== null ? error : {};
60
+ const code = typeof record["code"] === "string" ? record["code"] : void 0;
61
+ const status = typeof record["status"] === "number" ? record["status"] : null;
62
+ const signal = typeof record["signal"] === "string" ? record["signal"] : null;
63
+ const isKilled = code === "ETIMEDOUT";
64
+ let errorCode = status;
65
+ if (code === "ENOBUFS") {
66
+ errorCode = "ERR_CHILD_PROCESS_STDIO_MAXBUFFER";
67
+ } else if (code !== void 0 && !isKilled) {
68
+ errorCode = code;
69
+ }
70
+ return {
71
+ errorCode,
72
+ exitCode: status,
73
+ isKilled,
74
+ signal,
75
+ standardError: toText(record["stderr"]),
76
+ standardOutput: toText(record["stdout"])
77
+ };
78
+ }
79
+ function resolvePortOwnerQueryOutcome(params) {
80
+ return !params.hasFailed || params.platform !== "win32" && !params.isKilled && params.errorCode === LSOF_NOTHING_FOUND_EXIT_CODE && params.standardError.trim() === "" && params.standardOutput.trim() === "" ? "answered" : (0, import_host_process_query_verdict.resolveHostQueryFailure)(params);
81
+ }
82
+ function toText(stream) {
83
+ if (typeof stream === "string") {
84
+ return stream;
85
+ }
86
+ return import_node_buffer.Buffer.isBuffer(stream) ? stream.toString("utf-8") : "";
87
+ }
88
+ // Annotate the CommonJS export names for ESM import in node:
89
+ 0 && (module.exports = {
90
+ buildPortOwnerQueryMessage,
91
+ normalizeSyncExecError,
92
+ resolvePortOwnerQueryOutcome
93
+ });
94
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3BvcnQtb3duZXItcXVlcnktdmVyZGljdC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIFB1cmUgY2xhc3NpZmljYXRpb24gb2YgdGhlIHBvcnQtb3duZXIgcXVlcnkgXHUyMDE0IGBuZXRzdGF0IC1hbm9gIG9uIFdpbmRvd3MsXG4gKiBgbHNvZiAtdGkgdGNwOjxwb3J0PmAgZWxzZXdoZXJlIFx1MjAxNCBkZWNpZGluZywgZnJvbSBob3cgaXQgZW5kZWQsIHdoZXRoZXIgaXRcbiAqICoqYW5zd2VyZWQqKiBvciAqKmZhaWxlZCoqLCBhbmQgc2F5aW5nIHdoaWNoIGZhaWx1cmUgaW4gb25lIGxpbmUuXG4gKlxuICogVGhlIHF1ZXJ5IGlzIHRoZSBvbmx5IHJlYWwgZXNjYWxhdGlvbiB0aGUgQXBwaXVtIHRlYXJkb3duIGhhczogdGhlIFBJRCB0aGVcbiAqIGhhcm5lc3MgaG9sZHMgaXMgdGhlIGBzaGVsbDogdHJ1ZWAgd3JhcHBlciBpdCBzcGF3bmVkLCBzbyB3aGF0IHN1cnZpdmVzIGEga2lsbFxuICogaXMgZm91bmQgYnkgYXNraW5nIHdobyBzdGlsbCBsaXN0ZW5zIG9uIHRoZSBwb3J0ICgqKkw0NioqKS4gSXQgdXNlZCB0byByZXNvbHZlXG4gKiBhbiBlbXB0eSBsaXN0IGZvciBldmVyeSBlcnJvciwgd2hpY2ggbWFkZSB0aHJlZSBkaWZmZXJlbnQgZW5kaW5ncyBvbmUgc2lsZW50XG4gKiB2YWx1ZTpcbiAqXG4gKiAtIGBsc29mYCBleGl0aW5nIDEgd2l0aCBub3RoaW5nIG9uIGVpdGhlciBzdHJlYW0gXHUyMDE0IHdoaWNoIGlzIGhvdyBpdCBzYXlzXG4gKiAgIG5vdGhpbmcgaG9sZHMgdGhlIHBvcnQqLCBhIGxlZ2l0aW1hdGUgZW1wdHkgYW5zd2VyO1xuICogLSB0aGUgYnVkZ2V0IHJ1bm5pbmcgb3V0IG9uIGEgY29udGVuZGVkIGhvc3Q7XG4gKiAtIHRoZSBjaGlsZCBkeWluZy5cbiAqXG4gKiBPbmx5IHRoZSBmaXJzdCBpcyBhbiBhbnN3ZXIuIFRoZSBvdGhlciB0d28gZGlzYXJtIHRoZSBlc2NhbGF0aW9uIGV4YWN0bHkgdGhlXG4gKiB3YXkgYSBzaWxlbnRseSBmYWlsZWQgcHJvY2VzcyBsaXN0aW5nIGRpc2FybWVkIHRoZSBlbXVsYXRvcidzXG4gKiAoYGhvc3QtcHJvY2Vzcy1xdWVyeS12ZXJkaWN0LnRzYCksIHNvIHRoZXkgYXJlIGNsYXNzaWZpZWQgYnkgdGhlIHNhbWUgcnVsZXNcbiAqIGFuZCByZXBvcnRlZCwgbm90IHN3YWxsb3dlZC5cbiAqXG4gKiAqKldoeSBhIG1vZHVsZSBvZiBpdHMgb3duIHJhdGhlciB0aGFuIGFuIG9wdGlvbiBvbiB0aGUgcHJvY2Vzcy1saXN0aW5nXG4gKiB2ZXJkaWN0LioqIFRoZSB0d28gcXVlcmllcyBkaXNhZ3JlZSBpbiB0d28gcGxhY2VzLCBub3Qgb25lLiBaZXJvIG93bmVycyBpcyBhXG4gKiBsZWdpdGltYXRlIGFuc3dlciBoZXJlLCBzbyBgemVyby1yb3dzYCBuZXZlciBhcHBsaWVzOyBhbmQgYGxzb2ZgJ3Mgc2lsZW50IGV4aXRcbiAqIDEgbWVhbnMgKm5vdGhpbmcgbGlzdGVucyosIHdoZXJlIGZvciBgdGFza2xpc3RgIGEgc2lsZW50IG5vbi16ZXJvIGV4aXQgaXMgYVxuICogY3Jhc2guIFRoZSBmYWlsdXJlIGJyYW5jaGVzIHRoZW1zZWx2ZXMgYXJlIGRlbGVnYXRlZCB0b1xuICoge0BsaW5rIHJlc29sdmVIb3N0UXVlcnlGYWlsdXJlfSwgc28gdGhlcmUgaXMgc3RpbGwgb25lIGRlZmluaXRpb24gb2ZcbiAqIGBjcmFzaGVkYCwgYHRpbWVkLW91dGAgYW5kIGByZWZ1c2VkYC5cbiAqL1xuXG5pbXBvcnQgeyBCdWZmZXIgfSBmcm9tICdub2RlOmJ1ZmZlcic7XG5cbmltcG9ydCB0eXBlIHsgSG9zdFF1ZXJ5RmFpbHVyZSB9IGZyb20gJy4vaG9zdC1wcm9jZXNzLXF1ZXJ5LXZlcmRpY3QuY2pzJztcblxuaW1wb3J0IHtcbiAgZm9ybWF0RHVyYXRpb24sXG4gIGZvcm1hdEV4aXRDb2RlLFxuICBmb3JtYXRSZWZ1c2FsLFxuICByZXNvbHZlSG9zdFF1ZXJ5RmFpbHVyZVxufSBmcm9tICcuL2hvc3QtcHJvY2Vzcy1xdWVyeS12ZXJkaWN0LmNqcyc7XG5pbXBvcnQgeyBhc3NlcnROZXZlciB9IGZyb20gJy4vdHlwZS1ndWFyZHMuY2pzJztcblxuLyoqXG4gKiBUaGUgZXhpdCBjb2RlIGBsc29mYCB1c2VzIGZvciBcImZvdW5kIG5vdGhpbmdcIiwgd2hpY2ggaXQgcmVwb3J0cyBvbiBuZWl0aGVyIHN0cmVhbS5cbiAqL1xuY29uc3QgTFNPRl9OT1RISU5HX0ZPVU5EX0VYSVRfQ09ERSA9IDE7XG5cbi8qKlxuICogUGFyYW1ldGVycyBmb3Ige0BsaW5rIGJ1aWxkUG9ydE93bmVyUXVlcnlNZXNzYWdlfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBCdWlsZFBvcnRPd25lclF1ZXJ5TWVzc2FnZVBhcmFtcyB7XG4gIC8qKlxuICBUaGUgY29tbWFuZCB0aGF0IHdhcyBydW4sIGZvciB0aGUgcmVhZGVyIHRvIHRyeSBieSBoYW5kIFx1MjAxNCBlLmcuIGBuZXRzdGF0IC1hbm9gLlxuICAgKi9cbiAgcmVhZG9ubHkgY29tbWFuZDogc3RyaW5nO1xuXG4gIC8qKlxuICBIb3cgbG9uZyB0aGUgY2FsbCB0b29rIGJlZm9yZSBpdCBlbmRlZCwgaW4gbWlsbGlzZWNvbmRzLlxuICAgKi9cbiAgcmVhZG9ubHkgZWxhcHNlZEluTWlsbGlzZWNvbmRzOiBudW1iZXI7XG5cbiAgLyoqXG4gIFRoZSBjaGlsZCdzIGV4aXQgY29kZSwgd2hlbiBpdCBleGl0ZWQgcmF0aGVyIHRoYW4gZmFpbGluZyB0byBzdGFydCBvciBiZWluZyBraWxsZWQuXG4gICAqL1xuICByZWFkb25seSBleGl0Q29kZTogbnVsbCB8IG51bWJlcjtcblxuICAvKipcbiAgVGhlIHZlcmRpY3QgZnJvbSB7QGxpbmsgcmVzb2x2ZVBvcnRPd25lclF1ZXJ5T3V0Y29tZX0uXG4gICAqL1xuICByZWFkb25seSBvdXRjb21lOiBQb3J0T3duZXJRdWVyeU91dGNvbWU7XG5cbiAgLyoqXG4gIFRoZSBwb3J0IHdob3NlIG93bmVycyB3ZXJlIGFza2VkIGZvci5cbiAgICovXG4gIHJlYWRvbmx5IHBvcnQ6IG51bWJlcjtcblxuICAvKipcbiAgVGhlIHNpZ25hbCB0aGUgY2hpbGQgd2FzIGtpbGxlZCB3aXRoLCB3aGVuIGl0IHdhcyBraWxsZWQuXG4gICAqL1xuICByZWFkb25seSBzaWduYWw6IG51bGwgfCBzdHJpbmc7XG5cbiAgLyoqXG4gIFdoYXRldmVyIHRoZSBjaGlsZCB3cm90ZSB0byBzdGRlcnIuXG4gICAqL1xuICByZWFkb25seSBzdGFuZGFyZEVycm9yOiBzdHJpbmc7XG5cbiAgLyoqXG4gIFRoZSBidWRnZXQgdGhlIGNhbGwgd2FzIGdpdmVuLCBpbiBtaWxsaXNlY29uZHMuXG4gICAqL1xuICByZWFkb25seSB0aW1lb3V0SW5NaWxsaXNlY29uZHM6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBUaGUgZmllbGRzIHtAbGluayBub3JtYWxpemVTeW5jRXhlY0Vycm9yfSBleHRyYWN0cyBmcm9tIGFuIGBleGVjRmlsZVN5bmNgIHRocm93LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIE5vcm1hbGl6ZWRTeW5jRXhlY0Vycm9yIHtcbiAgLyoqXG4gIFRoZSBlcnJvciBjb2RlIGluIGBleGVjRmlsZWAncyB2b2NhYnVsYXJ5OiB0aGUgbnVtZXJpYyBleGl0IGNvZGUsIG9yIGEgc3RyaW5nIHN1Y2ggYXMgYEVOT0VOVGAgb3IgYEVSUl9DSElMRF9QUk9DRVNTX1NURElPX01BWEJVRkZFUmAuXG4gICAqL1xuICByZWFkb25seSBlcnJvckNvZGU6IG51bGwgfCBudW1iZXIgfCBzdHJpbmc7XG5cbiAgLyoqXG4gIFRoZSBjaGlsZCdzIGV4aXQgY29kZSwgd2hlbiBpdCBleGl0ZWQuXG4gICAqL1xuICByZWFkb25seSBleGl0Q29kZTogbnVsbCB8IG51bWJlcjtcblxuICAvKipcbiAgV2hldGhlciB0aGUgYnVkZ2V0IGV4cGlyZWQgYW5kIHRoZSBjaGlsZCB3YXMga2lsbGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgaXNLaWxsZWQ6IGJvb2xlYW47XG5cbiAgLyoqXG4gIFRoZSBzaWduYWwgdGhlIGNoaWxkIHdhcyBraWxsZWQgd2l0aC5cbiAgICovXG4gIHJlYWRvbmx5IHNpZ25hbDogbnVsbCB8IHN0cmluZztcblxuICAvKipcbiAgV2hhdGV2ZXIgdGhlIGNoaWxkIHdyb3RlIHRvIHN0ZGVyci5cbiAgICovXG4gIHJlYWRvbmx5IHN0YW5kYXJkRXJyb3I6IHN0cmluZztcblxuICAvKipcbiAgV2hhdGV2ZXIgdGhlIGNoaWxkIHdyb3RlIHRvIHN0ZG91dCBiZWZvcmUgaXQgZW5kZWQuXG4gICAqL1xuICByZWFkb25seSBzdGFuZGFyZE91dHB1dDogc3RyaW5nO1xufVxuXG4vKipcbiAqIEhvdyB0aGUgcG9ydC1vd25lciBxdWVyeSBlbmRlZC5cbiAqXG4gKiBgYW5zd2VyZWRgIGNvdmVycyBib3RoIGEgbGlzdGVuZXIgZm91bmQgYW5kIG5vbmUgZm91bmQgXHUyMDE0IHRoZSBxdWVyeSBzdWNjZWVkZWRcbiAqIGVpdGhlciB3YXkuIFRoZSByZXN0IGFyZSB7QGxpbmsgcmVzb2x2ZUhvc3RRdWVyeUZhaWx1cmV9J3MgZmFpbHVyZXMuXG4gKi9cbmV4cG9ydCB0eXBlIFBvcnRPd25lclF1ZXJ5T3V0Y29tZSA9ICdhbnN3ZXJlZCcgfCBIb3N0UXVlcnlGYWlsdXJlO1xuXG4vKipcbiAqIFBhcmFtZXRlcnMgZm9yIHtAbGluayByZXNvbHZlUG9ydE93bmVyUXVlcnlPdXRjb21lfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZXNvbHZlUG9ydE93bmVyUXVlcnlPdXRjb21lUGFyYW1zIHtcbiAgLyoqXG4gIGBleGVjRmlsZWAncyBgZXJyb3IuY29kZWA6IHRoZSBudW1lcmljIGV4aXQgY29kZSwgb3IgYSBzdHJpbmcgbGlrZSBgRU5PRU5UYCB3aGVuIHRoZSBjaGlsZCBuZXZlciByYW4uXG4gICAqL1xuICByZWFkb25seSBlcnJvckNvZGU6IG51bGwgfCBudW1iZXIgfCBzdHJpbmc7XG5cbiAgLyoqXG4gIFdoZXRoZXIgYGV4ZWNGaWxlYCByZXBvcnRlZCBhbiBlcnJvciBhdCBhbGwuXG4gICAqL1xuICByZWFkb25seSBoYXNGYWlsZWQ6IGJvb2xlYW47XG5cbiAgLyoqXG4gIGBleGVjRmlsZWAncyBgZXJyb3Iua2lsbGVkYDogd2hldGhlciB0aGUgYnVkZ2V0IGV4cGlyZWQgYW5kIHRoZSBjaGlsZCB3YXMga2lsbGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgaXNLaWxsZWQ6IGJvb2xlYW47XG5cbiAgLyoqXG4gIFRoZSBob3N0IHBsYXRmb3JtLCB3aGljaCBkZWNpZGVzIHdoZXRoZXIgYSBzaWxlbnQgZXhpdCAxIGlzIGBsc29mYCBzYXlpbmcgKm5vdGhpbmcgbGlzdGVucyouXG4gICAqL1xuICByZWFkb25seSBwbGF0Zm9ybTogTm9kZUpTLlBsYXRmb3JtO1xuXG4gIC8qKlxuICBXaGF0ZXZlciB0aGUgY2hpbGQgd3JvdGUgdG8gc3RkZXJyLlxuICAgKi9cbiAgcmVhZG9ubHkgc3RhbmRhcmRFcnJvcjogc3RyaW5nO1xuXG4gIC8qKlxuICBXaGF0ZXZlciB0aGUgY2hpbGQgd3JvdGUgdG8gc3Rkb3V0LlxuICAgKi9cbiAgcmVhZG9ubHkgc3RhbmRhcmRPdXRwdXQ6IHN0cmluZztcbn1cblxuLyoqXG4gKiBCdWlsZHMgdGhlIHNpbmdsZSBsaW5lIHRoZSBxdWVyeSBsb2dzIGZvciBhbiBvdXRjb21lLlxuICpcbiAqIEBwYXJhbSBwYXJhbXMgLSBUaGUgb3V0Y29tZSBwbHVzIHRoZSBjb21tYW5kLCB0aGUgcG9ydCwgdGhlIGJ1ZGdldCBhbmQgd2hhdCB0aGUgY2hpbGQgbGVmdCBiZWhpbmQuXG4gKiBAcmV0dXJucyBUaGUgd2FybmluZyB0byBsb2csIG9yIGB1bmRlZmluZWRgIHdoZW4gdGhlIHF1ZXJ5IGFuc3dlcmVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRQb3J0T3duZXJRdWVyeU1lc3NhZ2UocGFyYW1zOiBCdWlsZFBvcnRPd25lclF1ZXJ5TWVzc2FnZVBhcmFtcyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IGNvc3QgPSBgYWZ0ZXIgJHtmb3JtYXREdXJhdGlvbihwYXJhbXMuZWxhcHNlZEluTWlsbGlzZWNvbmRzKX1gO1xuICBjb25zdCBzdWJqZWN0ID0gYFxcYCR7cGFyYW1zLmNvbW1hbmR9XFxgIChhc2tpbmcgd2hvIGxpc3RlbnMgb24gcG9ydCAke1N0cmluZyhwYXJhbXMucG9ydCl9KWA7XG4gIGNvbnN0IGNvbnNlcXVlbmNlID0gYE5vdGhpbmcgaXMga25vd24gYWJvdXQgd2hhdCBzdGlsbCBob2xkcyBwb3J0ICR7U3RyaW5nKHBhcmFtcy5wb3J0KX0sIHNvIHRoZSBlc2NhbGF0aW9uIGhhcyBubyBQSUQgdG8ga2lsbCBcdTIwMTQgdGhpcyBpcyBub3QgdGhlIHNhbWUgYXMgbm90aGluZyBob2xkaW5nIGl0LmA7XG5cbiAgc3dpdGNoIChwYXJhbXMub3V0Y29tZSkge1xuICAgIGNhc2UgJ2Fuc3dlcmVkJzoge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgY2FzZSAnY3Jhc2hlZCc6IHtcbiAgICAgIHJldHVybiBgV2FybmluZzogJHtzdWJqZWN0fSBkaWVkICR7Y29zdH0gd2l0aG91dCBleHBsYWluaW5nIGl0c2VsZiAoZXhpdCAke2Zvcm1hdEV4aXRDb2RlKHBhcmFtcy5leGl0Q29kZSl9LCBub3RoaW5nIG9uIHN0ZGVycikuIFN1c3BlY3QgYSBjcmFzaCBvciBhbiBpbnRlcmZlcmluZyBzZWN1cml0eSBwcm9kdWN0LCBhbmQgdHJ5IHRoZSBjb21tYW5kIGJ5IGhhbmQuICR7Y29uc2VxdWVuY2V9YDtcbiAgICB9XG4gICAgY2FzZSAnbm90LWZvdW5kJzoge1xuICAgICAgcmV0dXJuIGBXYXJuaW5nOiAke3N1YmplY3R9IGNvdWxkIG5vdCBiZSBydW4gYXQgYWxsICR7Y29zdH06IHRoZSBleGVjdXRhYmxlIHdhcyBub3QgZm91bmQgb24gUEFUSC4gJHtjb25zZXF1ZW5jZX1gO1xuICAgIH1cbiAgICBjYXNlICdvdXRwdXQtb3ZlcnJhbic6IHtcbiAgICAgIHJldHVybiBgV2FybmluZzogJHtzdWJqZWN0fSBwcm9kdWNlZCBtb3JlIG91dHB1dCAke2Nvc3R9IHRoYW4gdGhlIHF1ZXJ5J3MgYnVmZmVyIGFsbG93cywgc28gbm9uZSBvZiBpdCBjb3VsZCBiZSByZWFkLiBSYWlzZSB0aGUgYnVmZmVyLiAke2NvbnNlcXVlbmNlfWA7XG4gICAgfVxuICAgIGNhc2UgJ3JlZnVzZWQnOiB7XG4gICAgICByZXR1cm4gYFdhcm5pbmc6ICR7c3ViamVjdH0gcmVmdXNlZCB0aGUgcmVxdWVzdCAke2Nvc3R9IChleGl0ICR7Zm9ybWF0RXhpdENvZGUocGFyYW1zLmV4aXRDb2RlKX0pOiAke2Zvcm1hdFJlZnVzYWwocGFyYW1zLnN0YW5kYXJkRXJyb3IpfSAke2NvbnNlcXVlbmNlfWA7XG4gICAgfVxuICAgIGNhc2UgJ3RpbWVkLW91dCc6IHtcbiAgICAgIHJldHVybiBgV2FybmluZzogJHtzdWJqZWN0fSBkaWQgbm90IGZpbmlzaCB3aXRoaW4gaXRzICR7Zm9ybWF0RHVyYXRpb24ocGFyYW1zLnRpbWVvdXRJbk1pbGxpc2Vjb25kcyl9IGJ1ZGdldCBhbmQgd2FzIGtpbGxlZCAke2Nvc3R9JHtwYXJhbXMuc2lnbmFsID09PSBudWxsID8gJycgOiBgICgke3BhcmFtcy5zaWduYWx9KWB9LiAke2NvbnNlcXVlbmNlfWA7XG4gICAgfVxuICAgIGRlZmF1bHQ6IHtcbiAgICAgIHJldHVybiBhc3NlcnROZXZlcihwYXJhbXMub3V0Y29tZSk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogRXh0cmFjdHMgd2hhdCBhbiBgZXhlY0ZpbGVTeW5jYCB0aHJvdyBjYXJyaWVzLCBpbiBgZXhlY0ZpbGVgJ3Mgdm9jYWJ1bGFyeS5cbiAqXG4gKiBUaGUgc3luY2hyb25vdXMgQVBJIHJlcG9ydHMgdGhlIHNhbWUgZW5kaW5ncyB3aXRoIGRpZmZlcmVudCBmaWVsZHM6IGFuXG4gKiBleHBpcmVkIGJ1ZGdldCBpcyBgY29kZTogJ0VUSU1FRE9VVCdgIHJhdGhlciB0aGFuIGBraWxsZWQ6IHRydWVgLCBhbiBvdmVycnVuXG4gKiBidWZmZXIgaXMgYEVOT0JVRlNgLCBhbmQgdGhlIGV4aXQgY29kZSBpcyBgc3RhdHVzYCByYXRoZXIgdGhhbiBgY29kZWAuXG4gKiBOb3JtYWxpemluZyBoZXJlIGxldHMgdGhlIHN5bmMgdGVhcmRvd24gY2xhc3NpZnkgd2l0aCB0aGUgc2FtZSB2ZXJkaWN0IGFzIHRoZVxuICogYXN5bmMgb25lLlxuICpcbiAqIEBwYXJhbSBlcnJvciAtIFdoYXRldmVyIGBleGVjRmlsZVN5bmNgIHRocmV3LlxuICogQHJldHVybnMgVGhlIG5vcm1hbGl6ZWQgZmllbGRzOyBhbiB1bnJlY29nbml6YWJsZSB0aHJvdyByZWFkcyBhcyBhIGNyYXNoIHdpdGggbm8gZXZpZGVuY2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBub3JtYWxpemVTeW5jRXhlY0Vycm9yKGVycm9yOiB1bmtub3duKTogTm9ybWFsaXplZFN5bmNFeGVjRXJyb3Ige1xuICBjb25zdCByZWNvcmQgPSB0eXBlb2YgZXJyb3IgPT09ICdvYmplY3QnICYmIGVycm9yICE9PSBudWxsID8gZXJyb3IgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4gOiB7fTtcbiAgY29uc3QgY29kZSA9IHR5cGVvZiByZWNvcmRbJ2NvZGUnXSA9PT0gJ3N0cmluZycgPyByZWNvcmRbJ2NvZGUnXSA6IHVuZGVmaW5lZDtcbiAgY29uc3Qgc3RhdHVzID0gdHlwZW9mIHJlY29yZFsnc3RhdHVzJ10gPT09ICdudW1iZXInID8gcmVjb3JkWydzdGF0dXMnXSA6IG51bGw7XG4gIGNvbnN0IHNpZ25hbCA9IHR5cGVvZiByZWNvcmRbJ3NpZ25hbCddID09PSAnc3RyaW5nJyA/IHJlY29yZFsnc2lnbmFsJ10gOiBudWxsO1xuICBjb25zdCBpc0tpbGxlZCA9IGNvZGUgPT09ICdFVElNRURPVVQnO1xuXG4gIGxldCBlcnJvckNvZGU6IG51bGwgfCBudW1iZXIgfCBzdHJpbmcgPSBzdGF0dXM7XG4gIGlmIChjb2RlID09PSAnRU5PQlVGUycpIHtcbiAgICBlcnJvckNvZGUgPSAnRVJSX0NISUxEX1BST0NFU1NfU1RESU9fTUFYQlVGRkVSJztcbiAgfSBlbHNlIGlmIChjb2RlICE9PSB1bmRlZmluZWQgJiYgIWlzS2lsbGVkKSB7XG4gICAgZXJyb3JDb2RlID0gY29kZTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgZXJyb3JDb2RlLFxuICAgIGV4aXRDb2RlOiBzdGF0dXMsXG4gICAgaXNLaWxsZWQsXG4gICAgc2lnbmFsLFxuICAgIHN0YW5kYXJkRXJyb3I6IHRvVGV4dChyZWNvcmRbJ3N0ZGVyciddKSxcbiAgICBzdGFuZGFyZE91dHB1dDogdG9UZXh0KHJlY29yZFsnc3Rkb3V0J10pXG4gIH07XG59XG5cbi8qKlxuICogRGVjaWRlcyBob3cgdGhlIHBvcnQtb3duZXIgcXVlcnkgZW5kZWQuXG4gKlxuICogQHBhcmFtIHBhcmFtcyAtIFdoYXQgYGV4ZWNGaWxlYCByZXBvcnRlZCwgYW5kIHRoZSBwbGF0Zm9ybSBpdCByYW4gb24uXG4gKiBAcmV0dXJucyBUaGUgb3V0Y29tZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVQb3J0T3duZXJRdWVyeU91dGNvbWUocGFyYW1zOiBSZXNvbHZlUG9ydE93bmVyUXVlcnlPdXRjb21lUGFyYW1zKTogUG9ydE93bmVyUXVlcnlPdXRjb21lIHtcbiAgcmV0dXJuICFwYXJhbXMuaGFzRmFpbGVkIHx8IChwYXJhbXMucGxhdGZvcm0gIT09ICd3aW4zMidcbiAgICAgICYmICFwYXJhbXMuaXNLaWxsZWRcbiAgICAgICYmIHBhcmFtcy5lcnJvckNvZGUgPT09IExTT0ZfTk9USElOR19GT1VORF9FWElUX0NPREVcbiAgICAgICYmIHBhcmFtcy5zdGFuZGFyZEVycm9yLnRyaW0oKSA9PT0gJydcbiAgICAgICYmIHBhcmFtcy5zdGFuZGFyZE91dHB1dC50cmltKCkgPT09ICcnKVxuICAgID8gJ2Fuc3dlcmVkJ1xuICAgIDogcmVzb2x2ZUhvc3RRdWVyeUZhaWx1cmUocGFyYW1zKTtcbn1cblxuLyoqXG4gKiBSZWFkcyBhIGNoaWxkJ3MgY2FwdHVyZWQgc3RyZWFtLCB3aGljaGV2ZXIgZm9ybSBgZXhlY0ZpbGVTeW5jYCBsZWZ0IGl0IGluLlxuICpcbiAqIEBwYXJhbSBzdHJlYW0gLSBBIHN0cmluZywgYSBgQnVmZmVyYCwgb3Igbm90aGluZy5cbiAqIEByZXR1cm5zIFRoZSB0ZXh0LCBvciBhbiBlbXB0eSBzdHJpbmcuXG4gKi9cbmZ1bmN0aW9uIHRvVGV4dChzdHJlYW06IHVua25vd24pOiBzdHJpbmcge1xuICBpZiAodHlwZW9mIHN0cmVhbSA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gc3RyZWFtO1xuICB9XG5cbiAgcmV0dXJuIEJ1ZmZlci5pc0J1ZmZlcihzdHJlYW0pID8gc3RyZWFtLnRvU3RyaW5nKCd1dGYtOCcpIDogJyc7XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQWdDQSx5QkFBdUI7QUFJdkIsd0NBS087QUFDUCx5QkFBNEI7QUFLNUIsTUFBTSwrQkFBK0I7QUFtSTlCLFNBQVMsMkJBQTJCLFFBQThEO0FBQ3ZHLFFBQU0sT0FBTyxhQUFTLGtEQUFlLE9BQU8scUJBQXFCLENBQUM7QUFDbEUsUUFBTSxVQUFVLEtBQUssT0FBTyxPQUFPLGtDQUFrQyxPQUFPLE9BQU8sSUFBSSxDQUFDO0FBQ3hGLFFBQU0sY0FBYyxnREFBZ0QsT0FBTyxPQUFPLElBQUksQ0FBQztBQUV2RixVQUFRLE9BQU8sU0FBUztBQUFBLElBQ3RCLEtBQUssWUFBWTtBQUNmLGFBQU87QUFBQSxJQUNUO0FBQUEsSUFDQSxLQUFLLFdBQVc7QUFDZCxhQUFPLFlBQVksT0FBTyxTQUFTLElBQUksd0NBQW9DLGtEQUFlLE9BQU8sUUFBUSxDQUFDLDBHQUEwRyxXQUFXO0FBQUEsSUFDak87QUFBQSxJQUNBLEtBQUssYUFBYTtBQUNoQixhQUFPLFlBQVksT0FBTyw0QkFBNEIsSUFBSSwyQ0FBMkMsV0FBVztBQUFBLElBQ2xIO0FBQUEsSUFDQSxLQUFLLGtCQUFrQjtBQUNyQixhQUFPLFlBQVksT0FBTyx5QkFBeUIsSUFBSSxtRkFBbUYsV0FBVztBQUFBLElBQ3ZKO0FBQUEsSUFDQSxLQUFLLFdBQVc7QUFDZCxhQUFPLFlBQVksT0FBTyx3QkFBd0IsSUFBSSxjQUFVLGtEQUFlLE9BQU8sUUFBUSxDQUFDLFVBQU0saURBQWMsT0FBTyxhQUFhLENBQUMsSUFBSSxXQUFXO0FBQUEsSUFDeko7QUFBQSxJQUNBLEtBQUssYUFBYTtBQUNoQixhQUFPLFlBQVksT0FBTyxrQ0FBOEIsa0RBQWUsT0FBTyxxQkFBcUIsQ0FBQywwQkFBMEIsSUFBSSxHQUFHLE9BQU8sV0FBVyxPQUFPLEtBQUssS0FBSyxPQUFPLE1BQU0sR0FBRyxLQUFLLFdBQVc7QUFBQSxJQUMxTTtBQUFBLElBQ0EsU0FBUztBQUNQLGlCQUFPLGdDQUFZLE9BQU8sT0FBTztBQUFBLElBQ25DO0FBQUEsRUFDRjtBQUNGO0FBY08sU0FBUyx1QkFBdUIsT0FBeUM7QUFDOUUsUUFBTSxTQUFTLE9BQU8sVUFBVSxZQUFZLFVBQVUsT0FBTyxRQUFtQyxDQUFDO0FBQ2pHLFFBQU0sT0FBTyxPQUFPLE9BQU8sTUFBTSxNQUFNLFdBQVcsT0FBTyxNQUFNLElBQUk7QUFDbkUsUUFBTSxTQUFTLE9BQU8sT0FBTyxRQUFRLE1BQU0sV0FBVyxPQUFPLFFBQVEsSUFBSTtBQUN6RSxRQUFNLFNBQVMsT0FBTyxPQUFPLFFBQVEsTUFBTSxXQUFXLE9BQU8sUUFBUSxJQUFJO0FBQ3pFLFFBQU0sV0FBVyxTQUFTO0FBRTFCLE1BQUksWUFBb0M7QUFDeEMsTUFBSSxTQUFTLFdBQVc7QUFDdEIsZ0JBQVk7QUFBQSxFQUNkLFdBQVcsU0FBUyxVQUFhLENBQUMsVUFBVTtBQUMxQyxnQkFBWTtBQUFBLEVBQ2Q7QUFFQSxTQUFPO0FBQUEsSUFDTDtBQUFBLElBQ0EsVUFBVTtBQUFBLElBQ1Y7QUFBQSxJQUNBO0FBQUEsSUFDQSxlQUFlLE9BQU8sT0FBTyxRQUFRLENBQUM7QUFBQSxJQUN0QyxnQkFBZ0IsT0FBTyxPQUFPLFFBQVEsQ0FBQztBQUFBLEVBQ3pDO0FBQ0Y7QUFRTyxTQUFTLDZCQUE2QixRQUFtRTtBQUM5RyxTQUFPLENBQUMsT0FBTyxhQUFjLE9BQU8sYUFBYSxXQUMxQyxDQUFDLE9BQU8sWUFDUixPQUFPLGNBQWMsZ0NBQ3JCLE9BQU8sY0FBYyxLQUFLLE1BQU0sTUFDaEMsT0FBTyxlQUFlLEtBQUssTUFBTSxLQUNwQyxpQkFDQSwyREFBd0IsTUFBTTtBQUNwQztBQVFBLFNBQVMsT0FBTyxRQUF5QjtBQUN2QyxNQUFJLE9BQU8sV0FBVyxVQUFVO0FBQzlCLFdBQU87QUFBQSxFQUNUO0FBRUEsU0FBTywwQkFBTyxTQUFTLE1BQU0sSUFBSSxPQUFPLFNBQVMsT0FBTyxJQUFJO0FBQzlEOyIsCiAgIm5hbWVzIjogW10KfQo=
@@ -0,0 +1,161 @@
1
+ /**
2
+ * @file
3
+ *
4
+ * Pure classification of the port-owner query — `netstat -ano` on Windows,
5
+ * `lsof -ti tcp:<port>` elsewhere — deciding, from how it ended, whether it
6
+ * **answered** or **failed**, and saying which failure in one line.
7
+ *
8
+ * The query is the only real escalation the Appium teardown has: the PID the
9
+ * harness holds is the `shell: true` wrapper it spawned, so what survives a kill
10
+ * is found by asking who still listens on the port (**L46**). It used to resolve
11
+ * an empty list for every error, which made three different endings one silent
12
+ * value:
13
+ *
14
+ * - `lsof` exiting 1 with nothing on either stream — which is how it says
15
+ * nothing holds the port*, a legitimate empty answer;
16
+ * - the budget running out on a contended host;
17
+ * - the child dying.
18
+ *
19
+ * Only the first is an answer. The other two disarm the escalation exactly the
20
+ * way a silently failed process listing disarmed the emulator's
21
+ * (`host-process-query-verdict.ts`), so they are classified by the same rules
22
+ * and reported, not swallowed.
23
+ *
24
+ * **Why a module of its own rather than an option on the process-listing
25
+ * verdict.** The two queries disagree in two places, not one. Zero owners is a
26
+ * legitimate answer here, so `zero-rows` never applies; and `lsof`'s silent exit
27
+ * 1 means *nothing listens*, where for `tasklist` a silent non-zero exit is a
28
+ * crash. The failure branches themselves are delegated to
29
+ * {@link resolveHostQueryFailure}, so there is still one definition of
30
+ * `crashed`, `timed-out` and `refused`.
31
+ */
32
+ import type { HostQueryFailure } from './host-process-query-verdict.cjs';
33
+ /**
34
+ * Parameters for {@link buildPortOwnerQueryMessage}.
35
+ */
36
+ export interface BuildPortOwnerQueryMessageParams {
37
+ /**
38
+ The command that was run, for the reader to try by hand — e.g. `netstat -ano`.
39
+ */
40
+ readonly command: string;
41
+ /**
42
+ How long the call took before it ended, in milliseconds.
43
+ */
44
+ readonly elapsedInMilliseconds: number;
45
+ /**
46
+ The child's exit code, when it exited rather than failing to start or being killed.
47
+ */
48
+ readonly exitCode: null | number;
49
+ /**
50
+ The verdict from {@link resolvePortOwnerQueryOutcome}.
51
+ */
52
+ readonly outcome: PortOwnerQueryOutcome;
53
+ /**
54
+ The port whose owners were asked for.
55
+ */
56
+ readonly port: number;
57
+ /**
58
+ The signal the child was killed with, when it was killed.
59
+ */
60
+ readonly signal: null | string;
61
+ /**
62
+ Whatever the child wrote to stderr.
63
+ */
64
+ readonly standardError: string;
65
+ /**
66
+ The budget the call was given, in milliseconds.
67
+ */
68
+ readonly timeoutInMilliseconds: number;
69
+ }
70
+ /**
71
+ * The fields {@link normalizeSyncExecError} extracts from an `execFileSync` throw.
72
+ */
73
+ export interface NormalizedSyncExecError {
74
+ /**
75
+ The error code in `execFile`'s vocabulary: the numeric exit code, or a string such as `ENOENT` or `ERR_CHILD_PROCESS_STDIO_MAXBUFFER`.
76
+ */
77
+ readonly errorCode: null | number | string;
78
+ /**
79
+ The child's exit code, when it exited.
80
+ */
81
+ readonly exitCode: null | number;
82
+ /**
83
+ Whether the budget expired and the child was killed.
84
+ */
85
+ readonly isKilled: boolean;
86
+ /**
87
+ The signal the child was killed with.
88
+ */
89
+ readonly signal: null | string;
90
+ /**
91
+ Whatever the child wrote to stderr.
92
+ */
93
+ readonly standardError: string;
94
+ /**
95
+ Whatever the child wrote to stdout before it ended.
96
+ */
97
+ readonly standardOutput: string;
98
+ }
99
+ /**
100
+ * How the port-owner query ended.
101
+ *
102
+ * `answered` covers both a listener found and none found — the query succeeded
103
+ * either way. The rest are {@link resolveHostQueryFailure}'s failures.
104
+ */
105
+ export type PortOwnerQueryOutcome = 'answered' | HostQueryFailure;
106
+ /**
107
+ * Parameters for {@link resolvePortOwnerQueryOutcome}.
108
+ */
109
+ export interface ResolvePortOwnerQueryOutcomeParams {
110
+ /**
111
+ `execFile`'s `error.code`: the numeric exit code, or a string like `ENOENT` when the child never ran.
112
+ */
113
+ readonly errorCode: null | number | string;
114
+ /**
115
+ Whether `execFile` reported an error at all.
116
+ */
117
+ readonly hasFailed: boolean;
118
+ /**
119
+ `execFile`'s `error.killed`: whether the budget expired and the child was killed.
120
+ */
121
+ readonly isKilled: boolean;
122
+ /**
123
+ The host platform, which decides whether a silent exit 1 is `lsof` saying *nothing listens*.
124
+ */
125
+ readonly platform: NodeJS.Platform;
126
+ /**
127
+ Whatever the child wrote to stderr.
128
+ */
129
+ readonly standardError: string;
130
+ /**
131
+ Whatever the child wrote to stdout.
132
+ */
133
+ readonly standardOutput: string;
134
+ }
135
+ /**
136
+ * Builds the single line the query logs for an outcome.
137
+ *
138
+ * @param params - The outcome plus the command, the port, the budget and what the child left behind.
139
+ * @returns The warning to log, or `undefined` when the query answered.
140
+ */
141
+ export declare function buildPortOwnerQueryMessage(params: BuildPortOwnerQueryMessageParams): string | undefined;
142
+ /**
143
+ * Extracts what an `execFileSync` throw carries, in `execFile`'s vocabulary.
144
+ *
145
+ * The synchronous API reports the same endings with different fields: an
146
+ * expired budget is `code: 'ETIMEDOUT'` rather than `killed: true`, an overrun
147
+ * buffer is `ENOBUFS`, and the exit code is `status` rather than `code`.
148
+ * Normalizing here lets the sync teardown classify with the same verdict as the
149
+ * async one.
150
+ *
151
+ * @param error - Whatever `execFileSync` threw.
152
+ * @returns The normalized fields; an unrecognizable throw reads as a crash with no evidence.
153
+ */
154
+ export declare function normalizeSyncExecError(error: unknown): NormalizedSyncExecError;
155
+ /**
156
+ * Decides how the port-owner query ended.
157
+ *
158
+ * @param params - What `execFile` reported, and the platform it ran on.
159
+ * @returns The outcome.
160
+ */
161
+ export declare function resolvePortOwnerQueryOutcome(params: ResolvePortOwnerQueryOutcomeParams): PortOwnerQueryOutcome;
@@ -23,7 +23,9 @@ __export(resolve_emulator_device_id_exports, {
23
23
  module.exports = __toCommonJS(resolve_emulator_device_id_exports);
24
24
  var import_adb_device_list = require("./adb-device-list.cjs");
25
25
  var import_adb = require("./adb.cjs");
26
+ var import_avd_name_channel = require("./avd-name-channel.cjs");
26
27
  var import_emulator_device_id = require("./emulator-device-id.cjs");
28
+ var import_emulator_reclaim = require("./emulator-reclaim.cjs");
27
29
  const EMULATOR_DEVICE_ID_PREFIX = "emulator-";
28
30
  async function resolveEmulatorDeviceId(params) {
29
31
  const candidates = await listEmulatorDeviceCandidates();
@@ -41,14 +43,35 @@ async function listEmulatorDeviceCandidates() {
41
43
  const deviceIds = (0, import_adb_device_list.listOnlineDeviceIds)(devicesOutput).filter((deviceId) => deviceId.startsWith(EMULATOR_DEVICE_ID_PREFIX));
42
44
  const candidates = [];
43
45
  for (const deviceId of deviceIds) {
44
- const output = await (0, import_adb.runAdbText)({ commandArguments: ["emu", "avd", "name"], deviceId });
45
- const avdName = output.split("\n", 1)[0]?.trim() ?? "";
46
- candidates.push({ avdName, deviceId });
46
+ candidates.push({ avdName: await probeAvdName(deviceId), deviceId });
47
47
  }
48
48
  return candidates;
49
49
  }
50
+ async function probeAvdName(deviceId) {
51
+ let channel = import_avd_name_channel.FIRST_AVD_NAME_CHANNEL;
52
+ while (channel !== void 0) {
53
+ let didChannelRespond = true;
54
+ let reportedAvdName = "";
55
+ try {
56
+ reportedAvdName = (0, import_avd_name_channel.parseAvdNameAnswer)(
57
+ await (0, import_adb.runAdbText)({
58
+ commandArguments: (0, import_avd_name_channel.buildAvdNameChannelCommand)(channel),
59
+ deviceId,
60
+ timeoutInMilliseconds: import_emulator_reclaim.ADB_DEVICE_CHECK_TIMEOUT_IN_MILLISECONDS
61
+ })
62
+ );
63
+ } catch {
64
+ didChannelRespond = false;
65
+ }
66
+ if (reportedAvdName.length > 0) {
67
+ return reportedAvdName;
68
+ }
69
+ channel = (0, import_avd_name_channel.resolveNextAvdNameChannel)({ channel, didChannelRespond });
70
+ }
71
+ return "";
72
+ }
50
73
  // Annotate the CommonJS export names for ESM import in node:
51
74
  0 && (module.exports = {
52
75
  resolveEmulatorDeviceId
53
76
  });
54
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3Jlc29sdmUtZW11bGF0b3ItZGV2aWNlLWlkLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBmaWxlXG4gKlxuICogQXNrcyB0aGUgcnVubmluZyBlbXVsYXRvcnMgd2hpY2ggQVZEIGVhY2ggd2FzIHN0YXJ0ZWQgZnJvbSwgYW5kIHJlc29sdmVzIG9uZVxuICogYnkgbmFtZSB0aHJvdWdoIHtAbGluayAuL2VtdWxhdG9yLWRldmljZS1pZC50c30ncyBzZWxlY3Rpb24uXG4gKlxuICogRXZlcnkgZnVuY3Rpb24gaGVyZSBzaGVsbHMgb3V0LCBzbyB0aGUgd2hvbGUgbW9kdWxlIGlzIGludGVncmF0aW9uLXRpbWUgY29kZVxuICogXHUyMDE0IHdoaWNoIGlzIGV4YWN0bHkgd2h5IHRoZSBzZWxlY3Rpb24gaXQgZGVsZWdhdGVzIHRvIGxpdmVzIGluIGl0cyBvd24gbW9kdWxlXG4gKiBhbmQgc3RheXMgdW5pdC10ZXN0ZWQuXG4gKi9cblxuLyogdjggaWdub3JlIHN0YXJ0IC0tIEludGVncmF0aW9uLXRpbWUgY29kZSAoc2hlbGxzIG91dCB0byBhIHJlYWwgZGV2aWNlKSBjb3ZlcmVkIGJ5IGludGVncmF0aW9uIHRlc3RzLCBub3QgdW5pdCB0ZXN0cy4gKi9cblxuaW1wb3J0IHR5cGUgeyBFbXVsYXRvckRldmljZUNhbmRpZGF0ZSB9IGZyb20gJy4vZW11bGF0b3ItZGV2aWNlLWlkLmNqcyc7XG5cbmltcG9ydCB7IGxpc3RPbmxpbmVEZXZpY2VJZHMgfSBmcm9tICcuL2FkYi1kZXZpY2UtbGlzdC5janMnO1xuaW1wb3J0IHtcbiAgcnVuQWRiVGV4dCxcbiAgcnVuQWRiVGV4dFdpdGhvdXREZXZpY2Vcbn0gZnJvbSAnLi9hZGIuY2pzJztcbmltcG9ydCB7IHNlbGVjdEVtdWxhdG9yRGV2aWNlSWQgfSBmcm9tICcuL2VtdWxhdG9yLWRldmljZS1pZC5janMnO1xuXG4vKipcbiAqIFBhcmFtZXRlcnMgZm9yIHtAbGluayByZXNvbHZlRW11bGF0b3JEZXZpY2VJZH0uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVzb2x2ZUVtdWxhdG9yRGV2aWNlSWRQYXJhbXMge1xuICAvKipcbiAgICogVGhlIEFWRCBuYW1lIHRvIG1hdGNoLCBlLmcuIGBvYnNpZGlhbl9zY3JlZW5zaG90c2AuXG4gICAqL1xuICByZWFkb25seSBhdmROYW1lOiBzdHJpbmc7XG59XG5cbi8qKlxuICogVGhlIHByZWZpeCBgYWRiIGRldmljZXNgIGdpdmVzIGFuIGVtdWxhdG9yLCBhcyBvcHBvc2VkIHRvIGEgcGh5c2ljYWxseSBhdHRhY2hlZCBkZXZpY2UuXG4gKi9cbmNvbnN0IEVNVUxBVE9SX0RFVklDRV9JRF9QUkVGSVggPSAnZW11bGF0b3ItJztcblxuLyoqXG4gKiBGaW5kcyB0aGUgcnVubmluZyBlbXVsYXRvciB3aG9zZSBBVkQgaXMgdGhlIG5hbWVkIG9uZS5cbiAqXG4gKiBAcGFyYW0gcGFyYW1zIC0gVGhlIEFWRCB0byBtYXRjaC5cbiAqIEByZXR1cm5zIEEge0BsaW5rIFByb21pc2V9IHRoYXQgcmVzb2x2ZXMgdG8gdGhlIGRldmljZSBVRElEIHRvIGFkZHJlc3MgaXQgYnkuXG4gKiBAdGhyb3dzIEVycm9yIGlmIG5vIHJ1bm5pbmcgZW11bGF0b3Igd2FzIHN0YXJ0ZWQgZnJvbSB0aGF0IEFWRC4gVGhlIG1lc3NhZ2UgbGlzdHMgd2hhdCBJUyBydW5uaW5nLCBzaW5jZVxuICogICBcInRoZSB3cm9uZyBlbXVsYXRvciBpcyB1cFwiIGFuZCBcIm5vIGVtdWxhdG9yIGlzIHVwXCIgbmVlZCBkaWZmZXJlbnQgYW5zd2Vycy5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlc29sdmVFbXVsYXRvckRldmljZUlkKHBhcmFtczogUmVzb2x2ZUVtdWxhdG9yRGV2aWNlSWRQYXJhbXMpOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCBjYW5kaWRhdGVzID0gYXdhaXQgbGlzdEVtdWxhdG9yRGV2aWNlQ2FuZGlkYXRlcygpO1xuICBjb25zdCBkZXZpY2VJZCA9IHNlbGVjdEVtdWxhdG9yRGV2aWNlSWQoeyBhdmROYW1lOiBwYXJhbXMuYXZkTmFtZSwgY2FuZGlkYXRlcyB9KTtcblxuICBpZiAoIWRldmljZUlkKSB7XG4gICAgY29uc3QgbGlzdGVkID0gY2FuZGlkYXRlcy5tYXAoKGNhbmRpZGF0ZSkgPT4gYCR7Y2FuZGlkYXRlLmRldmljZUlkfSAoJHtjYW5kaWRhdGUuYXZkTmFtZX0pYCkuam9pbignLCAnKSB8fCAnbm9uZSc7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYHJlc29sdmVFbXVsYXRvckRldmljZUlkOiBubyBydW5uaW5nIGVtdWxhdG9yIGZvciBBVkQgXCIke3BhcmFtcy5hdmROYW1lfVwiLiBSdW5uaW5nIGVtdWxhdG9yczogJHtsaXN0ZWR9LiBgXG4gICAgICAgICsgJ1N0YXJ0IGl0LCBvciBydW4gdGhpcyBwcm9qZWN0IG9uY2UgdG8gaGF2ZSB0aGUgaGFybmVzcyBzdGFydCBpdC4nXG4gICAgKTtcbiAgfVxuXG4gIHJldHVybiBkZXZpY2VJZDtcbn1cblxuLyoqXG4gKiBBc2tzIGV2ZXJ5IG9ubGluZSBlbXVsYXRvciB3aGljaCBBVkQgaXQgd2FzIHN0YXJ0ZWQgZnJvbS5cbiAqXG4gKiBAcmV0dXJucyBBIHtAbGluayBQcm9taXNlfSB0aGF0IHJlc29sdmVzIHRvIG9uZSBlbnRyeSBwZXIgcnVubmluZyBlbXVsYXRvci5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gbGlzdEVtdWxhdG9yRGV2aWNlQ2FuZGlkYXRlcygpOiBQcm9taXNlPEVtdWxhdG9yRGV2aWNlQ2FuZGlkYXRlW10+IHtcbiAgY29uc3QgZGV2aWNlc091dHB1dCA9IGF3YWl0IHJ1bkFkYlRleHRXaXRob3V0RGV2aWNlKFsnZGV2aWNlcyddKTtcbiAgY29uc3QgZGV2aWNlSWRzID0gbGlzdE9ubGluZURldmljZUlkcyhkZXZpY2VzT3V0cHV0KS5maWx0ZXIoKGRldmljZUlkKSA9PiBkZXZpY2VJZC5zdGFydHNXaXRoKEVNVUxBVE9SX0RFVklDRV9JRF9QUkVGSVgpKTtcblxuICBjb25zdCBjYW5kaWRhdGVzOiBFbXVsYXRvckRldmljZUNhbmRpZGF0ZVtdID0gW107XG4gIGZvciAoY29uc3QgZGV2aWNlSWQgb2YgZGV2aWNlSWRzKSB7XG4gICAgLy8gYGFkYiBlbXUgYXZkIG5hbWVgIGFuc3dlcnMgd2l0aCB0aGUgbmFtZSBhbmQgdGhlbiBgT0tgLCBlYWNoIG9uIGl0cyBvd24gbGluZS5cbiAgICBjb25zdCBvdXRwdXQgPSBhd2FpdCBydW5BZGJUZXh0KHsgY29tbWFuZEFyZ3VtZW50czogWydlbXUnLCAnYXZkJywgJ25hbWUnXSwgZGV2aWNlSWQgfSk7XG4gICAgY29uc3QgYXZkTmFtZSA9IG91dHB1dC5zcGxpdCgnXFxuJywgMSlbMF0/LnRyaW0oKSA/PyAnJztcbiAgICBjYW5kaWRhdGVzLnB1c2goeyBhdmROYW1lLCBkZXZpY2VJZCB9KTtcbiAgfVxuXG4gIHJldHVybiBjYW5kaWRhdGVzO1xufVxuXG4vKiB2OCBpZ25vcmUgc3RvcCAqL1xuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQWVBLDZCQUFvQztBQUNwQyxpQkFHTztBQUNQLGdDQUF1QztBQWV2QyxNQUFNLDRCQUE0QjtBQVVsQyxlQUFzQix3QkFBd0IsUUFBd0Q7QUFDcEcsUUFBTSxhQUFhLE1BQU0sNkJBQTZCO0FBQ3RELFFBQU0sZUFBVyxrREFBdUIsRUFBRSxTQUFTLE9BQU8sU0FBUyxXQUFXLENBQUM7QUFFL0UsTUFBSSxDQUFDLFVBQVU7QUFDYixVQUFNLFNBQVMsV0FBVyxJQUFJLENBQUMsY0FBYyxHQUFHLFVBQVUsUUFBUSxLQUFLLFVBQVUsT0FBTyxHQUFHLEVBQUUsS0FBSyxJQUFJLEtBQUs7QUFDM0csVUFBTSxJQUFJO0FBQUEsTUFDUix5REFBeUQsT0FBTyxPQUFPLHlCQUF5QixNQUFNO0FBQUEsSUFFeEc7QUFBQSxFQUNGO0FBRUEsU0FBTztBQUNUO0FBT0EsZUFBZSwrQkFBbUU7QUFDaEYsUUFBTSxnQkFBZ0IsVUFBTSxvQ0FBd0IsQ0FBQyxTQUFTLENBQUM7QUFDL0QsUUFBTSxnQkFBWSw0Q0FBb0IsYUFBYSxFQUFFLE9BQU8sQ0FBQyxhQUFhLFNBQVMsV0FBVyx5QkFBeUIsQ0FBQztBQUV4SCxRQUFNLGFBQXdDLENBQUM7QUFDL0MsYUFBVyxZQUFZLFdBQVc7QUFFaEMsVUFBTSxTQUFTLFVBQU0sdUJBQVcsRUFBRSxrQkFBa0IsQ0FBQyxPQUFPLE9BQU8sTUFBTSxHQUFHLFNBQVMsQ0FBQztBQUN0RixVQUFNLFVBQVUsT0FBTyxNQUFNLE1BQU0sQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLEtBQUs7QUFDcEQsZUFBVyxLQUFLLEVBQUUsU0FBUyxTQUFTLENBQUM7QUFBQSxFQUN2QztBQUVBLFNBQU87QUFDVDsiLAogICJuYW1lcyI6IFtdCn0K
77
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3Jlc29sdmUtZW11bGF0b3ItZGV2aWNlLWlkLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBmaWxlXG4gKlxuICogQXNrcyB0aGUgcnVubmluZyBlbXVsYXRvcnMgd2hpY2ggQVZEIGVhY2ggd2FzIHN0YXJ0ZWQgZnJvbSwgYW5kIHJlc29sdmVzIG9uZVxuICogYnkgbmFtZSB0aHJvdWdoIHtAbGluayAuL2VtdWxhdG9yLWRldmljZS1pZC50c30ncyBzZWxlY3Rpb24uXG4gKlxuICogRXZlcnkgZnVuY3Rpb24gaGVyZSBzaGVsbHMgb3V0LCBzbyB0aGUgd2hvbGUgbW9kdWxlIGlzIGludGVncmF0aW9uLXRpbWUgY29kZVxuICogXHUyMDE0IHdoaWNoIGlzIGV4YWN0bHkgd2h5IHRoZSBzZWxlY3Rpb24gaXQgZGVsZWdhdGVzIHRvIGxpdmVzIGluIGl0cyBvd24gbW9kdWxlXG4gKiBhbmQgc3RheXMgdW5pdC10ZXN0ZWQuXG4gKi9cblxuLyogdjggaWdub3JlIHN0YXJ0IC0tIEludGVncmF0aW9uLXRpbWUgY29kZSAoc2hlbGxzIG91dCB0byBhIHJlYWwgZGV2aWNlKSBjb3ZlcmVkIGJ5IGludGVncmF0aW9uIHRlc3RzLCBub3QgdW5pdCB0ZXN0cy4gKi9cblxuaW1wb3J0IHR5cGUgeyBBdmROYW1lQ2hhbm5lbCB9IGZyb20gJy4vYXZkLW5hbWUtY2hhbm5lbC5janMnO1xuaW1wb3J0IHR5cGUgeyBFbXVsYXRvckRldmljZUNhbmRpZGF0ZSB9IGZyb20gJy4vZW11bGF0b3ItZGV2aWNlLWlkLmNqcyc7XG5cbmltcG9ydCB7IGxpc3RPbmxpbmVEZXZpY2VJZHMgfSBmcm9tICcuL2FkYi1kZXZpY2UtbGlzdC5janMnO1xuaW1wb3J0IHtcbiAgcnVuQWRiVGV4dCxcbiAgcnVuQWRiVGV4dFdpdGhvdXREZXZpY2Vcbn0gZnJvbSAnLi9hZGIuY2pzJztcbmltcG9ydCB7XG4gIGJ1aWxkQXZkTmFtZUNoYW5uZWxDb21tYW5kLFxuICBGSVJTVF9BVkRfTkFNRV9DSEFOTkVMLFxuICBwYXJzZUF2ZE5hbWVBbnN3ZXIsXG4gIHJlc29sdmVOZXh0QXZkTmFtZUNoYW5uZWxcbn0gZnJvbSAnLi9hdmQtbmFtZS1jaGFubmVsLmNqcyc7XG5pbXBvcnQgeyBzZWxlY3RFbXVsYXRvckRldmljZUlkIH0gZnJvbSAnLi9lbXVsYXRvci1kZXZpY2UtaWQuY2pzJztcbmltcG9ydCB7IEFEQl9ERVZJQ0VfQ0hFQ0tfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMgfSBmcm9tICcuL2VtdWxhdG9yLXJlY2xhaW0uY2pzJztcblxuLyoqXG4gKiBQYXJhbWV0ZXJzIGZvciB7QGxpbmsgcmVzb2x2ZUVtdWxhdG9yRGV2aWNlSWR9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlc29sdmVFbXVsYXRvckRldmljZUlkUGFyYW1zIHtcbiAgLyoqXG4gICAqIFRoZSBBVkQgbmFtZSB0byBtYXRjaCwgZS5nLiBgb2JzaWRpYW5fc2NyZWVuc2hvdHNgLlxuICAgKi9cbiAgcmVhZG9ubHkgYXZkTmFtZTogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBwcmVmaXggYGFkYiBkZXZpY2VzYCBnaXZlcyBhbiBlbXVsYXRvciwgYXMgb3Bwb3NlZCB0byBhIHBoeXNpY2FsbHkgYXR0YWNoZWQgZGV2aWNlLlxuICovXG5jb25zdCBFTVVMQVRPUl9ERVZJQ0VfSURfUFJFRklYID0gJ2VtdWxhdG9yLSc7XG5cbi8qKlxuICogRmluZHMgdGhlIHJ1bm5pbmcgZW11bGF0b3Igd2hvc2UgQVZEIGlzIHRoZSBuYW1lZCBvbmUuXG4gKlxuICogQHBhcmFtIHBhcmFtcyAtIFRoZSBBVkQgdG8gbWF0Y2guXG4gKiBAcmV0dXJucyBBIHtAbGluayBQcm9taXNlfSB0aGF0IHJlc29sdmVzIHRvIHRoZSBkZXZpY2UgVURJRCB0byBhZGRyZXNzIGl0IGJ5LlxuICogQHRocm93cyBFcnJvciBpZiBubyBydW5uaW5nIGVtdWxhdG9yIHdhcyBzdGFydGVkIGZyb20gdGhhdCBBVkQuIFRoZSBtZXNzYWdlIGxpc3RzIHdoYXQgSVMgcnVubmluZywgc2luY2VcbiAqICAgXCJ0aGUgd3JvbmcgZW11bGF0b3IgaXMgdXBcIiBhbmQgXCJubyBlbXVsYXRvciBpcyB1cFwiIG5lZWQgZGlmZmVyZW50IGFuc3dlcnMuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXNvbHZlRW11bGF0b3JEZXZpY2VJZChwYXJhbXM6IFJlc29sdmVFbXVsYXRvckRldmljZUlkUGFyYW1zKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3QgY2FuZGlkYXRlcyA9IGF3YWl0IGxpc3RFbXVsYXRvckRldmljZUNhbmRpZGF0ZXMoKTtcbiAgY29uc3QgZGV2aWNlSWQgPSBzZWxlY3RFbXVsYXRvckRldmljZUlkKHsgYXZkTmFtZTogcGFyYW1zLmF2ZE5hbWUsIGNhbmRpZGF0ZXMgfSk7XG5cbiAgaWYgKCFkZXZpY2VJZCkge1xuICAgIGNvbnN0IGxpc3RlZCA9IGNhbmRpZGF0ZXMubWFwKChjYW5kaWRhdGUpID0+IGAke2NhbmRpZGF0ZS5kZXZpY2VJZH0gKCR7Y2FuZGlkYXRlLmF2ZE5hbWV9KWApLmpvaW4oJywgJykgfHwgJ25vbmUnO1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGByZXNvbHZlRW11bGF0b3JEZXZpY2VJZDogbm8gcnVubmluZyBlbXVsYXRvciBmb3IgQVZEIFwiJHtwYXJhbXMuYXZkTmFtZX1cIi4gUnVubmluZyBlbXVsYXRvcnM6ICR7bGlzdGVkfS4gYFxuICAgICAgICArICdTdGFydCBpdCwgb3IgcnVuIHRoaXMgcHJvamVjdCBvbmNlIHRvIGhhdmUgdGhlIGhhcm5lc3Mgc3RhcnQgaXQuJ1xuICAgICk7XG4gIH1cblxuICByZXR1cm4gZGV2aWNlSWQ7XG59XG5cbi8qKlxuICogQXNrcyBldmVyeSBvbmxpbmUgZW11bGF0b3Igd2hpY2ggQVZEIGl0IHdhcyBzdGFydGVkIGZyb20uXG4gKlxuICogKipBIGRldmljZSB0aGF0IHdpbGwgbm90IGlkZW50aWZ5IGl0c2VsZiBpcyBsaXN0ZWQgd2l0aCBhbiBlbXB0eSBuYW1lLCBub3RcbiAqIHRocm93biBvdmVyLioqIEl0IGlzIHNvbWVib2R5IGVsc2UncyB3ZWRnZWQgZW11bGF0b3IgZmFyIG1vcmUgb2Z0ZW4gdGhhbiBpdCBpc1xuICogdGhpcyBjYWxsZXIncywgYW5kIGZhaWxpbmcgdGhlIHdob2xlIGxvb2t1cCBvdmVyIGl0IGlzIHByZWNpc2VseSB0aGVcbiAqIG1hY2hpbmUtd2lkZSBpbnRlcmxvY2sgYGF2ZC1uYW1lLWNoYW5uZWwudHNgIGV4aXN0cyB0byB1bmRvIFx1MjAxNCB0aGUgd2FudGVkXG4gKiBlbXVsYXRvciwgc2l0dGluZyByaWdodCBiZXNpZGUgaXQgYW5kIGFuc3dlcmluZyBwZXJmZWN0bHksIGlzIHN0aWxsIGZvdW5kLlxuICpcbiAqIEByZXR1cm5zIEEge0BsaW5rIFByb21pc2V9IHRoYXQgcmVzb2x2ZXMgdG8gb25lIGVudHJ5IHBlciBydW5uaW5nIGVtdWxhdG9yLlxuICovXG5hc3luYyBmdW5jdGlvbiBsaXN0RW11bGF0b3JEZXZpY2VDYW5kaWRhdGVzKCk6IFByb21pc2U8RW11bGF0b3JEZXZpY2VDYW5kaWRhdGVbXT4ge1xuICBjb25zdCBkZXZpY2VzT3V0cHV0ID0gYXdhaXQgcnVuQWRiVGV4dFdpdGhvdXREZXZpY2UoWydkZXZpY2VzJ10pO1xuICBjb25zdCBkZXZpY2VJZHMgPSBsaXN0T25saW5lRGV2aWNlSWRzKGRldmljZXNPdXRwdXQpLmZpbHRlcigoZGV2aWNlSWQpID0+IGRldmljZUlkLnN0YXJ0c1dpdGgoRU1VTEFUT1JfREVWSUNFX0lEX1BSRUZJWCkpO1xuXG4gIGNvbnN0IGNhbmRpZGF0ZXM6IEVtdWxhdG9yRGV2aWNlQ2FuZGlkYXRlW10gPSBbXTtcbiAgZm9yIChjb25zdCBkZXZpY2VJZCBvZiBkZXZpY2VJZHMpIHtcbiAgICBjYW5kaWRhdGVzLnB1c2goeyBhdmROYW1lOiBhd2FpdCBwcm9iZUF2ZE5hbWUoZGV2aWNlSWQpLCBkZXZpY2VJZCB9KTtcbiAgfVxuXG4gIHJldHVybiBjYW5kaWRhdGVzO1xufVxuXG4vKipcbiAqIEFza3Mgb25lIGVtdWxhdG9yIHdoaWNoIEFWRCBpdCB3YXMgc3RhcnRlZCBmcm9tLCBvdmVyIGVhY2ggY2hhbm5lbCBpbiB0dXJuLlxuICpcbiAqIFRoZSBndWVzdCBwcm9wZXJ0eSBjb21lcyBmaXJzdCBiZWNhdXNlIGl0IHRyYXZlbHMgYGFkYmRgIFx1MjAxNCB0aGUgY2hhbm5lbCB0aGlzXG4gKiBsb29rdXAgbmVlZHMgYW55d2F5IFx1MjAxNCB3aGlsZSB0aGUgY29uc29sZSBpcyBhIHNlcGFyYXRlIHBvcnQgdGhhdCB3ZWRnZXMgb24gaXRzXG4gKiBvd247IHNlZSBgYXZkLW5hbWUtY2hhbm5lbC50c2AuIEV2ZXJ5IGNhbGwgaXMgYm91bmRlZCwgc28gb25lIHVucmVzcG9uc2l2ZVxuICogZGV2aWNlIGNvc3RzIGEgdGltZW91dCByYXRoZXIgdGhhbiB0aGUgd2hvbGUgbG9va3VwLlxuICpcbiAqIEBwYXJhbSBkZXZpY2VJZCAtIFRoZSBlbXVsYXRvciB0byBhc2suXG4gKiBAcmV0dXJucyBBIHtAbGluayBQcm9taXNlfSB0aGF0IHJlc29sdmVzIHRvIHRoZSBBVkQgbmFtZSwgb3IgYCcnYCB3aGVuIG5vIGNoYW5uZWwgaWRlbnRpZmllZCBpdC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gcHJvYmVBdmROYW1lKGRldmljZUlkOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICBsZXQgY2hhbm5lbDogQXZkTmFtZUNoYW5uZWwgfCB1bmRlZmluZWQgPSBGSVJTVF9BVkRfTkFNRV9DSEFOTkVMO1xuXG4gIHdoaWxlIChjaGFubmVsICE9PSB1bmRlZmluZWQpIHtcbiAgICBsZXQgZGlkQ2hhbm5lbFJlc3BvbmQgPSB0cnVlO1xuICAgIGxldCByZXBvcnRlZEF2ZE5hbWUgPSAnJztcblxuICAgIHRyeSB7XG4gICAgICByZXBvcnRlZEF2ZE5hbWUgPSBwYXJzZUF2ZE5hbWVBbnN3ZXIoXG4gICAgICAgIGF3YWl0IHJ1bkFkYlRleHQoe1xuICAgICAgICAgIGNvbW1hbmRBcmd1bWVudHM6IGJ1aWxkQXZkTmFtZUNoYW5uZWxDb21tYW5kKGNoYW5uZWwpLFxuICAgICAgICAgIGRldmljZUlkLFxuICAgICAgICAgIHRpbWVvdXRJbk1pbGxpc2Vjb25kczogQURCX0RFVklDRV9DSEVDS19USU1FT1VUX0lOX01JTExJU0VDT05EU1xuICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIGRpZENoYW5uZWxSZXNwb25kID0gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKHJlcG9ydGVkQXZkTmFtZS5sZW5ndGggPiAwKSB7XG4gICAgICByZXR1cm4gcmVwb3J0ZWRBdmROYW1lO1xuICAgIH1cblxuICAgIGNoYW5uZWwgPSByZXNvbHZlTmV4dEF2ZE5hbWVDaGFubmVsKHsgY2hhbm5lbCwgZGlkQ2hhbm5lbFJlc3BvbmQgfSk7XG4gIH1cblxuICByZXR1cm4gJyc7XG59XG5cbi8qIHY4IGlnbm9yZSBzdG9wICovXG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBZ0JBLDZCQUFvQztBQUNwQyxpQkFHTztBQUNQLDhCQUtPO0FBQ1AsZ0NBQXVDO0FBQ3ZDLDhCQUF5RDtBQWV6RCxNQUFNLDRCQUE0QjtBQVVsQyxlQUFzQix3QkFBd0IsUUFBd0Q7QUFDcEcsUUFBTSxhQUFhLE1BQU0sNkJBQTZCO0FBQ3RELFFBQU0sZUFBVyxrREFBdUIsRUFBRSxTQUFTLE9BQU8sU0FBUyxXQUFXLENBQUM7QUFFL0UsTUFBSSxDQUFDLFVBQVU7QUFDYixVQUFNLFNBQVMsV0FBVyxJQUFJLENBQUMsY0FBYyxHQUFHLFVBQVUsUUFBUSxLQUFLLFVBQVUsT0FBTyxHQUFHLEVBQUUsS0FBSyxJQUFJLEtBQUs7QUFDM0csVUFBTSxJQUFJO0FBQUEsTUFDUix5REFBeUQsT0FBTyxPQUFPLHlCQUF5QixNQUFNO0FBQUEsSUFFeEc7QUFBQSxFQUNGO0FBRUEsU0FBTztBQUNUO0FBYUEsZUFBZSwrQkFBbUU7QUFDaEYsUUFBTSxnQkFBZ0IsVUFBTSxvQ0FBd0IsQ0FBQyxTQUFTLENBQUM7QUFDL0QsUUFBTSxnQkFBWSw0Q0FBb0IsYUFBYSxFQUFFLE9BQU8sQ0FBQyxhQUFhLFNBQVMsV0FBVyx5QkFBeUIsQ0FBQztBQUV4SCxRQUFNLGFBQXdDLENBQUM7QUFDL0MsYUFBVyxZQUFZLFdBQVc7QUFDaEMsZUFBVyxLQUFLLEVBQUUsU0FBUyxNQUFNLGFBQWEsUUFBUSxHQUFHLFNBQVMsQ0FBQztBQUFBLEVBQ3JFO0FBRUEsU0FBTztBQUNUO0FBYUEsZUFBZSxhQUFhLFVBQW1DO0FBQzdELE1BQUksVUFBc0M7QUFFMUMsU0FBTyxZQUFZLFFBQVc7QUFDNUIsUUFBSSxvQkFBb0I7QUFDeEIsUUFBSSxrQkFBa0I7QUFFdEIsUUFBSTtBQUNGLDRCQUFrQjtBQUFBLFFBQ2hCLFVBQU0sdUJBQVc7QUFBQSxVQUNmLHNCQUFrQixvREFBMkIsT0FBTztBQUFBLFVBQ3BEO0FBQUEsVUFDQSx1QkFBdUI7QUFBQSxRQUN6QixDQUFDO0FBQUEsTUFDSDtBQUFBLElBQ0YsUUFBUTtBQUNOLDBCQUFvQjtBQUFBLElBQ3RCO0FBRUEsUUFBSSxnQkFBZ0IsU0FBUyxHQUFHO0FBQzlCLGFBQU87QUFBQSxJQUNUO0FBRUEsa0JBQVUsbURBQTBCLEVBQUUsU0FBUyxrQkFBa0IsQ0FBQztBQUFBLEVBQ3BFO0FBRUEsU0FBTztBQUNUOyIsCiAgIm5hbWVzIjogW10KfQo=
@@ -47,4 +47,4 @@ async function importSharp(caller) {
47
47
  0 && (module.exports = {
48
48
  importSharp
49
49
  });
50
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3NoYXJwLWxvYWRlci50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIExhemlseSBsb2FkcyBgc2hhcnBgLCB0aGUgT1BUSU9OQUwgcGVlciBkZXBlbmRlbmN5IHRoZSBpbWFnZSBoZWxwZXJzIG5lZWQsIGFuZFxuICogZGVzY3JpYmVzIHRoZSBzbGljZSBvZiBpdHMgc3VyZmFjZSB0aGV5IHVzZS5cbiAqXG4gKiBUaGUgbG9hZCBpcyBkZWZlcnJlZCBiZWNhdXNlIGEgc3RhdGljIGltcG9ydCB3b3VsZCBkcmFnIGBzaGFycGAnc1xuICogcGxhdGZvcm0tc3BlY2lmaWMgbmF0aXZlIGJpbmFyaWVzIGludG8gZXZlcnkgY29uc3VtZXIgb2YgdGhpcyBwYWNrYWdlJ3MgaW5kZXgsXG4gKiB3aGVuIG9ubHkgc2NyZWVuc2hvdCBwb3N0LXByb2Nlc3NpbmcgbmVlZHMgdGhlbS4gVGhlIHR5cGUgaXMgc3RydWN0dXJhbCBmb3JcbiAqIHRoZSBzYW1lIHJlYXNvbjogdGhpcyBtb2R1bGUgdHlwZS1jaGVja3Mgd2l0aG91dCBgc2hhcnBgJ3Mgb3duIHR5cGVzIGJlaW5nXG4gKiByZXNvbHZhYmxlLlxuICovXG5cbi8qKlxuICogQSBsYXllciBwYXNzZWQgdG8gYHNoYXJwYCdzIGBjb21wb3NpdGVgLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNoYXJwQ29tcG9zaXRlTGF5ZXIge1xuICByZWFkb25seSBpbnB1dDogQnVmZmVyO1xuICByZWFkb25seSBsZWZ0OiBudW1iZXI7XG4gIHJlYWRvbmx5IHRvcDogbnVtYmVyO1xufVxuXG4vKipcbiAqIFRoZSBgc2hhcnBgIGVudHJ5IHBvaW50IHRoZSBpbWFnZSBoZWxwZXJzIHVzZS5cbiAqL1xuZXhwb3J0IHR5cGUgU2hhcnBGYWN0b3J5ID0gKGlucHV0OiBVaW50OEFycmF5KSA9PiBTaGFycEluc3RhbmNlO1xuXG4vKipcbiAqIE9uZSBgc2hhcnBgIHBpcGVsaW5lLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNoYXJwSW5zdGFuY2Uge1xuICBibHVyOiAodGhpczogdm9pZCwgc2lnbWE6IG51bWJlcikgPT4gU2hhcnBJbnN0YW5jZTtcbiAgY29tcG9zaXRlOiAodGhpczogdm9pZCwgbGF5ZXJzOiBTaGFycENvbXBvc2l0ZUxheWVyW10pID0+IFNoYXJwSW5zdGFuY2U7XG4gIG1ldGFkYXRhOiAodGhpczogdm9pZCkgPT4gUHJvbWlzZTxTaGFycE1ldGFkYXRhPjtcbiAgcG5nOiAodGhpczogdm9pZCkgPT4gU2hhcnBJbnN0YW5jZTtcbiAgcmVzaXplOiAodGhpczogdm9pZCwgd2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIsIG9wdGlvbnM/OiBTaGFycFJlc2l6ZU9wdGlvbnMpID0+IFNoYXJwSW5zdGFuY2U7XG4gIHRvQnVmZmVyOiAodGhpczogdm9pZCkgPT4gUHJvbWlzZTxCdWZmZXI+O1xuICB0cmltOiAodGhpczogdm9pZCwgb3B0aW9uczogU2hhcnBUcmltT3B0aW9ucykgPT4gU2hhcnBJbnN0YW5jZTtcbn1cblxuLyoqXG4gKiBUaGUgc3Vic2V0IG9mIGBzaGFycGAncyBtZXRhZGF0YSB0aGUgaW1hZ2UgaGVscGVycyByZWFkLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNoYXJwTWV0YWRhdGEge1xuICByZWFkb25seSBoZWlnaHQ/OiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIHJlYWRvbmx5IHdpZHRoPzogbnVtYmVyIHwgdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIFRoZSBzdWJzZXQgb2YgYHNoYXJwYCdzIHJlc2l6ZSBvcHRpb25zIHRoZSBpbWFnZSBoZWxwZXJzIHNldC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTaGFycFJlc2l6ZU9wdGlvbnMge1xuICByZWFkb25seSBmaXQ6ICdjb3ZlcicgfCAnZmlsbCc7XG59XG5cbi8qKlxuICogVGhlIHN1YnNldCBvZiBgc2hhcnBgJ3MgdHJpbSBvcHRpb25zIHRoZSBpbWFnZSBoZWxwZXJzIHNldC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTaGFycFRyaW1PcHRpb25zIHtcbiAgLyoqXG4gICAqIEhvdyBmYXIgYSBwaXhlbCBtYXkgZGlmZmVyIGZyb20gdGhlIHRyaW1tZWQtYXdheSBjb2xvciBiZWZvcmUgaXQgY291bnRzIGFzXG4gICAqIGNvbnRlbnQuXG4gICAqL1xuICByZWFkb25seSB0aHJlc2hvbGQ6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBMb2FkcyBgc2hhcnBgIG9uIGRlbWFuZC5cbiAqXG4gKiBAcGFyYW0gY2FsbGVyIC0gTmFtZSBvZiB0aGUgY2FsbGluZyBoZWxwZXIsIHNvIHRoZSBlcnJvciBzYXlzIHdoaWNoIG9uZSBuZWVkcyBpdC5cbiAqIEByZXR1cm5zIEEge0BsaW5rIFByb21pc2V9IHRoYXQgcmVzb2x2ZXMgdG8gdGhlIGBzaGFycGAgZmFjdG9yeS5cbiAqIEB0aHJvd3MgRXJyb3IgbmFtaW5nIHRoZSBtaXNzaW5nIG9wdGlvbmFsIHBlZXIgZGVwZW5kZW5jeS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGltcG9ydFNoYXJwKGNhbGxlcjogc3RyaW5nKTogUHJvbWlzZTxTaGFycEZhY3Rvcnk+IHtcbiAgdHJ5IHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcmVzdHJpY3RlZC1zeW50YXggLS0gYHNoYXJwYCBpcyBhbiBPUFRJT05BTCBwZWVyLCBzbyBpdCBtdXN0IGJlIGxvYWRlZCBsYXppbHk6IGEgc3RhdGljIGltcG9ydCB3b3VsZCBkcmFnIGl0cyBuYXRpdmUgYmluYXJpZXMgaW50byBldmVyeSBjb25zdW1lciBvZiB0aGlzIHBhY2thZ2UncyBpbmRleC5cbiAgICBjb25zdCBzaGFycE1vZHVsZSA9IGF3YWl0IGltcG9ydCgnc2hhcnAnKTtcbiAgICBjb25zdCBmYWN0b3J5OiB1bmtub3duID0gc2hhcnBNb2R1bGUuZGVmYXVsdDtcbiAgICByZXR1cm4gZmFjdG9yeSBhcyBTaGFycEZhY3Rvcnk7XG4gIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgLyogdjggaWdub3JlIHN0YXJ0IC0tIFJlYWNoZWQgb25seSB3aGVuIHRoZSBvcHRpb25hbCBwZWVyIGlzIGFic2VudCwgd2hpY2ggaXQgbmV2ZXIgaXMgaW4gdGhpcyBwYWNrYWdlJ3Mgb3duIHRlc3QgcnVuLiAqL1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGAke2NhbGxlcn0gbmVlZHMgdGhlIG9wdGlvbmFsIHBlZXIgZGVwZW5kZW5jeSBcInNoYXJwXCIuIGBcbiAgICAgICAgKyAnSW5zdGFsbCBpdCBpbiB0aGUgY29uc3VtaW5nIHByb2plY3QgKG5wbSBpIC1EIHNoYXJwKS4nLFxuICAgICAgeyBjYXVzZTogZXJyb3IgfVxuICAgICk7XG4gICAgLyogdjggaWdub3JlIHN0b3AgKi9cbiAgfVxufVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUF5RUEsZUFBc0IsWUFBWSxRQUF1QztBQUN2RSxNQUFJO0FBRUYsVUFBTSxjQUFjLE1BQU0sT0FBTyxPQUFPO0FBQ3hDLFVBQU0sVUFBbUIsWUFBWTtBQUNyQyxXQUFPO0FBQUEsRUFDVCxTQUFTLE9BQWdCO0FBRXZCLFVBQU0sSUFBSTtBQUFBLE1BQ1IsR0FBRyxNQUFNO0FBQUEsTUFFVCxFQUFFLE9BQU8sTUFBTTtBQUFBLElBQ2pCO0FBQUEsRUFFRjtBQUNGOyIsCiAgIm5hbWVzIjogW10KfQo=
50
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3NoYXJwLWxvYWRlci50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIExhemlseSBsb2FkcyBgc2hhcnBgLCB0aGUgT1BUSU9OQUwgcGVlciBkZXBlbmRlbmN5IHRoZSBpbWFnZSBoZWxwZXJzIG5lZWQsIGFuZFxuICogZGVzY3JpYmVzIHRoZSBzbGljZSBvZiBpdHMgc3VyZmFjZSB0aGV5IHVzZS5cbiAqXG4gKiBUaGUgbG9hZCBpcyBkZWZlcnJlZCBiZWNhdXNlIGEgc3RhdGljIGltcG9ydCB3b3VsZCBkcmFnIGBzaGFycGAnc1xuICogcGxhdGZvcm0tc3BlY2lmaWMgbmF0aXZlIGJpbmFyaWVzIGludG8gZXZlcnkgY29uc3VtZXIgb2YgdGhpcyBwYWNrYWdlJ3MgaW5kZXgsXG4gKiB3aGVuIG9ubHkgc2NyZWVuc2hvdCBwb3N0LXByb2Nlc3NpbmcgbmVlZHMgdGhlbS4gVGhlIHR5cGUgaXMgc3RydWN0dXJhbCBmb3JcbiAqIHRoZSBzYW1lIHJlYXNvbjogdGhpcyBtb2R1bGUgdHlwZS1jaGVja3Mgd2l0aG91dCBgc2hhcnBgJ3Mgb3duIHR5cGVzIGJlaW5nXG4gKiByZXNvbHZhYmxlLlxuICovXG5cbi8qKlxuICogQSBsYXllciBwYXNzZWQgdG8gYHNoYXJwYCdzIGBjb21wb3NpdGVgLlxuICpcbiAqIFRoZSBpbnB1dCBpcyBlaXRoZXIgYnl0ZXMgdG8gZHJhdyBcdTIwMTQgYW4gU1ZHLCBhIFBORyBcdTIwMTQgb3IgYSBibG9jayBgc2hhcnBgIGNyZWF0ZXNcbiAqIG9uIHRoZSBzcG90LCB3aGljaCBpcyBob3cgYSBmbGF0IGZpbGwgaXMgY29tcG9zaXRlZCB3aXRob3V0IGJ1aWxkaW5nIGFuIGltYWdlXG4gKiBmb3IgaXQgZmlyc3QuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2hhcnBDb21wb3NpdGVMYXllciB7XG4gIHJlYWRvbmx5IGlucHV0OiBCdWZmZXIgfCBTaGFycENyZWF0ZUlucHV0O1xuICByZWFkb25seSBsZWZ0OiBudW1iZXI7XG4gIHJlYWRvbmx5IHRvcDogbnVtYmVyO1xufVxuXG4vKipcbiAqIEEgc29saWQgYmxvY2sgb2YgY29sb3IsIGNyZWF0ZWQgYnkgYHNoYXJwYCByYXRoZXIgdGhhbiBzdXBwbGllZCBhcyBieXRlcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTaGFycENyZWF0ZUlucHV0IHtcbiAgcmVhZG9ubHkgY3JlYXRlOiBTaGFycENyZWF0ZVNwZWM7XG59XG5cbi8qKlxuICogVGhlIGJsb2NrIGBzaGFycGAgaXMgYXNrZWQgdG8gY3JlYXRlOiBhIHJlY3RhbmdsZSBvZiBvbmUgZmxhdCBjb2xvci5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTaGFycENyZWF0ZVNwZWMge1xuICByZWFkb25seSBiYWNrZ3JvdW5kOiBTaGFycFJnYkNvbG9yO1xuICByZWFkb25seSBjaGFubmVsczogbnVtYmVyO1xuICByZWFkb25seSBoZWlnaHQ6IG51bWJlcjtcbiAgcmVhZG9ubHkgd2lkdGg6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBUaGUgYHNoYXJwYCBlbnRyeSBwb2ludCB0aGUgaW1hZ2UgaGVscGVycyB1c2UuXG4gKi9cbmV4cG9ydCB0eXBlIFNoYXJwRmFjdG9yeSA9IChpbnB1dDogVWludDhBcnJheSkgPT4gU2hhcnBJbnN0YW5jZTtcblxuLyoqXG4gKiBPbmUgYHNoYXJwYCBwaXBlbGluZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTaGFycEluc3RhbmNlIHtcbiAgYmx1cjogKHRoaXM6IHZvaWQsIHNpZ21hOiBudW1iZXIpID0+IFNoYXJwSW5zdGFuY2U7XG4gIGNvbXBvc2l0ZTogKHRoaXM6IHZvaWQsIGxheWVyczogU2hhcnBDb21wb3NpdGVMYXllcltdKSA9PiBTaGFycEluc3RhbmNlO1xuICBlbnN1cmVBbHBoYTogKHRoaXM6IHZvaWQpID0+IFNoYXJwSW5zdGFuY2U7XG4gIG1ldGFkYXRhOiAodGhpczogdm9pZCkgPT4gUHJvbWlzZTxTaGFycE1ldGFkYXRhPjtcbiAgcG5nOiAodGhpczogdm9pZCkgPT4gU2hhcnBJbnN0YW5jZTtcbiAgcmF3OiAodGhpczogdm9pZCkgPT4gU2hhcnBJbnN0YW5jZTtcbiAgcmVzaXplOiAodGhpczogdm9pZCwgd2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIsIG9wdGlvbnM/OiBTaGFycFJlc2l6ZU9wdGlvbnMpID0+IFNoYXJwSW5zdGFuY2U7XG4gIHRvQnVmZmVyOiBTaGFycFRvQnVmZmVyO1xuICB0cmltOiAodGhpczogdm9pZCwgb3B0aW9uczogU2hhcnBUcmltT3B0aW9ucykgPT4gU2hhcnBJbnN0YW5jZTtcbn1cblxuLyoqXG4gKiBUaGUgc3Vic2V0IG9mIGBzaGFycGAncyBtZXRhZGF0YSB0aGUgaW1hZ2UgaGVscGVycyByZWFkLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNoYXJwTWV0YWRhdGEge1xuICByZWFkb25seSBoZWlnaHQ/OiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIHJlYWRvbmx5IHdpZHRoPzogbnVtYmVyIHwgdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIFRoZSBnZW9tZXRyeSByYXcgcGl4ZWxzIGhhdmUgdG8gYmUgcmVhZCB3aXRoIFx1MjAxNCB3aXRob3V0IGl0IHRoZXkgYXJlIGEgZmxhdCBydW4gb2YgYnl0ZXMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2hhcnBSYXdJbmZvIHtcbiAgcmVhZG9ubHkgY2hhbm5lbHM6IG51bWJlcjtcbiAgcmVhZG9ubHkgaGVpZ2h0OiBudW1iZXI7XG4gIHJlYWRvbmx5IHdpZHRoOiBudW1iZXI7XG59XG5cbi8qKlxuICogQSBmcmFtZSdzIHJhdyBwaXhlbHMgYW5kIHRoZSBnZW9tZXRyeSB0aGV5IGhhdmUgdG8gYmUgcmVhZCB3aXRoLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNoYXJwUmF3UmVzdWx0IHtcbiAgcmVhZG9ubHkgZGF0YTogVWludDhBcnJheTtcbiAgcmVhZG9ubHkgaW5mbzogU2hhcnBSYXdJbmZvO1xufVxuXG4vKipcbiAqIFRoZSBzdWJzZXQgb2YgYHNoYXJwYCdzIHJlc2l6ZSBvcHRpb25zIHRoZSBpbWFnZSBoZWxwZXJzIHNldC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTaGFycFJlc2l6ZU9wdGlvbnMge1xuICByZWFkb25seSBmaXQ6ICdjb3ZlcicgfCAnZmlsbCc7XG59XG5cbi8qKlxuICogQXNrcyBgdG9CdWZmZXJgIGZvciB0aGUgcGl4ZWxzIEFORCB0aGUgZ2VvbWV0cnkgdGhleSBhcmUgdG8gYmUgcmVhZCB3aXRoLlxuICpcbiAqIExpdGVyYWwgYHRydWVgIHJhdGhlciB0aGFuIGBib29sZWFuYCwgc28gdGhlIG92ZXJsb2FkIHRoYXQgcmV0dXJuc1xuICoge0BsaW5rIFNoYXJwUmF3UmVzdWx0fSBpcyBvbmx5IHNlbGVjdGVkIHdoZW4gdGhlIGdlb21ldHJ5IGlzIGdlbnVpbmVseSBjb21pbmdcbiAqIGJhY2sgXHUyMDE0IGEgYGZhbHNlYCB3b3VsZCByZXNvbHZlIHRvIGJhcmUgYnl0ZXMgd2l0aCB0aGUgd2lkdGggc2lsZW50bHkgbWlzc2luZy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTaGFycFJlc29sdmVXaXRoT2JqZWN0T3B0aW9ucyB7XG4gIHJlYWRvbmx5IHJlc29sdmVXaXRoT2JqZWN0OiB0cnVlO1xufVxuXG4vKipcbiAqIEEgY29sb3IgYXMgYHNoYXJwYCBuYW1lcyBpdHMgY2hhbm5lbHMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2hhcnBSZ2JDb2xvciB7XG4gIHJlYWRvbmx5IGI6IG51bWJlcjtcbiAgcmVhZG9ubHkgZzogbnVtYmVyO1xuICByZWFkb25seSByOiBudW1iZXI7XG59XG5cbi8qKlxuICogYHNoYXJwYCdzIGB0b0J1ZmZlcmAsIGluIHRoZSB0d28gc2hhcGVzIHRoZSBpbWFnZSBoZWxwZXJzIGNhbGwgaXQgaW4uXG4gKlxuICogV3JpdHRlbiBhcyBhbiBvdmVybG9hZGVkIGNhbGwgc2lnbmF0dXJlIHJhdGhlciB0aGFuIGEgdW5pb24gcmV0dXJuLCBiZWNhdXNlXG4gKiB3aGljaCBvbmUgY29tZXMgYmFjayBpcyBkZWNpZGVkIGJ5IHRoZSBhcmd1bWVudCBhbmQgYSBjYWxsZXIgc2hvdWxkIG5vdCBoYXZlXG4gKiB0byBuYXJyb3cgYSByZXN1bHQgaXQgYWxyZWFkeSBrbm93cyB0aGUgc2hhcGUgb2YuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2hhcnBUb0J1ZmZlciB7XG4gICh0aGlzOiB2b2lkKTogUHJvbWlzZTxCdWZmZXI+O1xuICAodGhpczogdm9pZCwgb3B0aW9uczogU2hhcnBSZXNvbHZlV2l0aE9iamVjdE9wdGlvbnMpOiBQcm9taXNlPFNoYXJwUmF3UmVzdWx0Pjtcbn1cblxuLyoqXG4gKiBUaGUgc3Vic2V0IG9mIGBzaGFycGAncyB0cmltIG9wdGlvbnMgdGhlIGltYWdlIGhlbHBlcnMgc2V0LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNoYXJwVHJpbU9wdGlvbnMge1xuICAvKipcbiAgICogSG93IGZhciBhIHBpeGVsIG1heSBkaWZmZXIgZnJvbSB0aGUgdHJpbW1lZC1hd2F5IGNvbG9yIGJlZm9yZSBpdCBjb3VudHMgYXNcbiAgICogY29udGVudC5cbiAgICovXG4gIHJlYWRvbmx5IHRocmVzaG9sZDogbnVtYmVyO1xufVxuXG4vKipcbiAqIExvYWRzIGBzaGFycGAgb24gZGVtYW5kLlxuICpcbiAqIEBwYXJhbSBjYWxsZXIgLSBOYW1lIG9mIHRoZSBjYWxsaW5nIGhlbHBlciwgc28gdGhlIGVycm9yIHNheXMgd2hpY2ggb25lIG5lZWRzIGl0LlxuICogQHJldHVybnMgQSB7QGxpbmsgUHJvbWlzZX0gdGhhdCByZXNvbHZlcyB0byB0aGUgYHNoYXJwYCBmYWN0b3J5LlxuICogQHRocm93cyBFcnJvciBuYW1pbmcgdGhlIG1pc3Npbmcgb3B0aW9uYWwgcGVlciBkZXBlbmRlbmN5LlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaW1wb3J0U2hhcnAoY2FsbGVyOiBzdHJpbmcpOiBQcm9taXNlPFNoYXJwRmFjdG9yeT4ge1xuICB0cnkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1yZXN0cmljdGVkLXN5bnRheCAtLSBgc2hhcnBgIGlzIGFuIE9QVElPTkFMIHBlZXIsIHNvIGl0IG11c3QgYmUgbG9hZGVkIGxhemlseTogYSBzdGF0aWMgaW1wb3J0IHdvdWxkIGRyYWcgaXRzIG5hdGl2ZSBiaW5hcmllcyBpbnRvIGV2ZXJ5IGNvbnN1bWVyIG9mIHRoaXMgcGFja2FnZSdzIGluZGV4LlxuICAgIGNvbnN0IHNoYXJwTW9kdWxlID0gYXdhaXQgaW1wb3J0KCdzaGFycCcpO1xuICAgIGNvbnN0IGZhY3Rvcnk6IHVua25vd24gPSBzaGFycE1vZHVsZS5kZWZhdWx0O1xuICAgIHJldHVybiBmYWN0b3J5IGFzIFNoYXJwRmFjdG9yeTtcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAvKiB2OCBpZ25vcmUgc3RhcnQgLS0gUmVhY2hlZCBvbmx5IHdoZW4gdGhlIG9wdGlvbmFsIHBlZXIgaXMgYWJzZW50LCB3aGljaCBpdCBuZXZlciBpcyBpbiB0aGlzIHBhY2thZ2UncyBvd24gdGVzdCBydW4uICovXG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYCR7Y2FsbGVyfSBuZWVkcyB0aGUgb3B0aW9uYWwgcGVlciBkZXBlbmRlbmN5IFwic2hhcnBcIi4gYFxuICAgICAgICArICdJbnN0YWxsIGl0IGluIHRoZSBjb25zdW1pbmcgcHJvamVjdCAobnBtIGkgLUQgc2hhcnApLicsXG4gICAgICB7IGNhdXNlOiBlcnJvciB9XG4gICAgKTtcbiAgICAvKiB2OCBpZ25vcmUgc3RvcCAqL1xuICB9XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQWlKQSxlQUFzQixZQUFZLFFBQXVDO0FBQ3ZFLE1BQUk7QUFFRixVQUFNLGNBQWMsTUFBTSxPQUFPLE9BQU87QUFDeEMsVUFBTSxVQUFtQixZQUFZO0FBQ3JDLFdBQU87QUFBQSxFQUNULFNBQVMsT0FBZ0I7QUFFdkIsVUFBTSxJQUFJO0FBQUEsTUFDUixHQUFHLE1BQU07QUFBQSxNQUVULEVBQUUsT0FBTyxNQUFNO0FBQUEsSUFDakI7QUFBQSxFQUVGO0FBQ0Y7IiwKICAibmFtZXMiOiBbXQp9Cg==