obsidian-integration-testing 12.0.0 → 12.1.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/dist/lib/cjs/adb-device-list.cjs +54 -0
- package/dist/lib/cjs/adb-device-list.d.cts +72 -0
- package/dist/lib/cjs/android-sdk.cjs +52 -0
- package/dist/lib/cjs/android-sdk.d.cts +29 -0
- package/dist/lib/cjs/app-startup-progress.cjs +87 -0
- package/dist/lib/cjs/app-startup-progress.d.cts +128 -0
- package/dist/lib/cjs/appium-server-marker.cjs +29 -32
- package/dist/lib/cjs/appium-server-marker.d.cts +22 -0
- package/dist/lib/cjs/avd-probe-verdict.cjs +90 -0
- package/dist/lib/cjs/avd-probe-verdict.d.cts +175 -0
- package/dist/lib/cjs/community-plugin-registry.cjs +1 -1
- package/dist/lib/cjs/community-plugin-registry.d.cts +1 -1
- package/dist/lib/cjs/config-directory-fallback-error.cjs +57 -0
- package/dist/lib/cjs/config-directory-fallback-error.d.cts +64 -0
- package/dist/lib/cjs/config-directory.cjs +46 -0
- package/dist/lib/cjs/config-directory.d.cts +45 -0
- package/dist/lib/cjs/connect-to-cdp.cjs +13 -7
- package/dist/lib/cjs/connect-to-cdp.d.cts +19 -0
- package/dist/lib/cjs/demo-vault-bootstrap.cjs +1 -1
- package/dist/lib/cjs/demo-vault-bootstrap.d.cts +3 -2
- package/dist/lib/cjs/demo-vault-populate.cjs +3 -2
- package/dist/lib/cjs/device-readiness.cjs +38 -3
- package/dist/lib/cjs/device-readiness.d.cts +83 -9
- package/dist/lib/cjs/emulator-arguments.cjs +6 -2
- package/dist/lib/cjs/emulator-arguments.d.cts +26 -0
- package/dist/lib/cjs/emulator-backend.cjs +71 -0
- package/dist/lib/cjs/emulator-backend.d.cts +76 -0
- package/dist/lib/cjs/emulator-liveness.cjs +72 -0
- package/dist/lib/cjs/emulator-liveness.d.cts +158 -0
- package/dist/lib/cjs/emulator-snapshot.cjs +57 -0
- package/dist/lib/cjs/emulator-snapshot.d.cts +68 -0
- package/dist/lib/cjs/global-setup-core.cjs +30 -30
- package/dist/lib/cjs/global-setup-core.d.cts +27 -2
- package/dist/lib/cjs/headless-vault-config.cjs +51 -0
- package/dist/lib/cjs/headless-vault-config.d.cts +67 -0
- package/dist/lib/cjs/index.cjs +12 -1
- package/dist/lib/cjs/index.d.cts +6 -1
- package/dist/lib/cjs/library.cjs +1 -1
- package/dist/lib/cjs/mobile-input.cjs +14 -2
- package/dist/lib/cjs/mobile-input.d.cts +5 -9
- package/dist/lib/cjs/namespace-bootstrap.cjs +1 -1
- package/dist/lib/cjs/obsidian-instance.cjs +52 -3
- package/dist/lib/cjs/obsidian-instance.d.cts +12 -0
- package/dist/lib/cjs/open-obsidian-settings-tab.cjs +1 -1
- package/dist/lib/cjs/open-obsidian-settings-tab.d.cts +3 -2
- package/dist/lib/cjs/owned-instance-exit-marker.cjs +99 -0
- package/dist/lib/cjs/owned-instance-exit-marker.d.cts +106 -0
- package/dist/lib/cjs/owned-instance-exited-error.cjs +106 -0
- package/dist/lib/cjs/owned-instance-exited-error.d.cts +98 -0
- package/dist/lib/cjs/owned-vault-seed.cjs +9 -5
- package/dist/lib/cjs/owned-vault-seed.d.cts +24 -3
- package/dist/lib/cjs/parent-liveness.cjs +42 -5
- package/dist/lib/cjs/parent-liveness.d.cts +37 -5
- package/dist/lib/cjs/port-owner.cjs +61 -0
- package/dist/lib/cjs/port-owner.d.cts +47 -0
- package/dist/lib/cjs/process-capture.cjs +62 -0
- package/dist/lib/cjs/process-capture.d.cts +83 -0
- package/dist/lib/cjs/process-exit-message.cjs +14 -8
- package/dist/lib/cjs/process-exit-message.d.cts +37 -3
- package/dist/lib/cjs/process-liveness.cjs +51 -0
- package/dist/lib/cjs/process-liveness.d.cts +18 -0
- package/dist/lib/cjs/run-version-matrix.cjs +1 -1
- package/dist/lib/cjs/run-version-matrix.d.cts +1 -1
- package/dist/lib/cjs/teardown-verdict.cjs +53 -0
- package/dist/lib/cjs/teardown-verdict.d.cts +69 -0
- package/dist/lib/cjs/temporary-vault.cjs +43 -8
- package/dist/lib/cjs/temporary-vault.d.cts +47 -5
- package/dist/lib/cjs/transport-appium.cjs +102 -17
- package/dist/lib/cjs/transport-appium.d.cts +53 -3
- package/dist/lib/cjs/transport-desktop-cdp.cjs +195 -6
- package/dist/lib/cjs/transport-desktop-cdp.d.cts +99 -0
- package/dist/lib/cjs/transport-factory.cjs +951 -133
- package/dist/lib/cjs/transport-options.cjs +11 -3
- package/dist/lib/cjs/transport-options.d.cts +131 -12
- package/dist/lib/cjs/transport.cjs +1 -1
- package/dist/lib/cjs/transport.d.cts +7 -1
- package/dist/lib/cjs/vault-plugin-install.cjs +40 -0
- package/dist/lib/cjs/vault-plugin-install.d.cts +64 -0
- package/dist/lib/cjs/vault-teardown-verdict.cjs +42 -0
- package/dist/lib/cjs/vault-teardown-verdict.d.cts +57 -0
- package/dist/lib/cjs/version-matrix.cjs +1 -1
- package/dist/lib/cjs/version-matrix.d.cts +2 -2
- package/dist/lib/cjs/webview-cdp.cjs +6 -7
- package/dist/lib/cjs/webview-cdp.d.cts +5 -1
- package/dist/lib/esm/adb-device-list.d.mts +72 -0
- package/dist/lib/esm/adb-device-list.mjs +28 -0
- package/dist/lib/esm/android-sdk.d.mts +29 -0
- package/dist/lib/esm/android-sdk.mjs +18 -0
- package/dist/lib/esm/app-startup-progress.d.mts +128 -0
- package/dist/lib/esm/app-startup-progress.mjs +59 -0
- package/dist/lib/esm/appium-server-marker.d.mts +22 -0
- package/dist/lib/esm/appium-server-marker.mjs +28 -22
- package/dist/lib/esm/avd-probe-verdict.d.mts +175 -0
- package/dist/lib/esm/avd-probe-verdict.mjs +62 -0
- package/dist/lib/esm/community-plugin-registry.d.mts +1 -1
- package/dist/lib/esm/community-plugin-registry.mjs +1 -1
- package/dist/lib/esm/config-directory-fallback-error.d.mts +64 -0
- package/dist/lib/esm/config-directory-fallback-error.mjs +33 -0
- package/dist/lib/esm/config-directory.d.mts +45 -0
- package/dist/lib/esm/config-directory.mjs +21 -0
- package/dist/lib/esm/connect-to-cdp.d.mts +19 -0
- package/dist/lib/esm/connect-to-cdp.mjs +13 -7
- package/dist/lib/esm/demo-vault-bootstrap.d.mts +3 -2
- package/dist/lib/esm/demo-vault-bootstrap.mjs +1 -1
- package/dist/lib/esm/demo-vault-populate.mjs +3 -2
- package/dist/lib/esm/device-readiness.d.mts +83 -9
- package/dist/lib/esm/device-readiness.mjs +34 -2
- package/dist/lib/esm/emulator-arguments.d.mts +26 -0
- package/dist/lib/esm/emulator-arguments.mjs +6 -2
- package/dist/lib/esm/emulator-backend.d.mts +76 -0
- package/dist/lib/esm/emulator-backend.mjs +45 -0
- package/dist/lib/esm/emulator-liveness.d.mts +158 -0
- package/dist/lib/esm/emulator-liveness.mjs +47 -0
- package/dist/lib/esm/emulator-snapshot.d.mts +68 -0
- package/dist/lib/esm/emulator-snapshot.mjs +32 -0
- package/dist/lib/esm/global-setup-core.d.mts +27 -2
- package/dist/lib/esm/global-setup-core.mjs +34 -35
- package/dist/lib/esm/headless-vault-config.d.mts +67 -0
- package/dist/lib/esm/headless-vault-config.mjs +31 -0
- package/dist/lib/esm/index.d.mts +6 -1
- package/dist/lib/esm/index.mjs +11 -1
- package/dist/lib/esm/library.mjs +1 -1
- package/dist/lib/esm/mobile-input.d.mts +5 -9
- package/dist/lib/esm/mobile-input.mjs +14 -2
- package/dist/lib/esm/namespace-bootstrap.mjs +1 -1
- package/dist/lib/esm/obsidian-instance.d.mts +12 -0
- package/dist/lib/esm/obsidian-instance.mjs +55 -3
- package/dist/lib/esm/open-obsidian-settings-tab.d.mts +3 -2
- package/dist/lib/esm/open-obsidian-settings-tab.mjs +1 -1
- package/dist/lib/esm/owned-instance-exit-marker.d.mts +106 -0
- package/dist/lib/esm/owned-instance-exit-marker.mjs +78 -0
- package/dist/lib/esm/owned-instance-exited-error.d.mts +98 -0
- package/dist/lib/esm/owned-instance-exited-error.mjs +81 -0
- package/dist/lib/esm/owned-vault-seed.d.mts +24 -3
- package/dist/lib/esm/owned-vault-seed.mjs +9 -5
- package/dist/lib/esm/parent-liveness.d.mts +37 -5
- package/dist/lib/esm/parent-liveness.mjs +42 -5
- package/dist/lib/esm/port-owner.d.mts +47 -0
- package/dist/lib/esm/port-owner.mjs +36 -0
- package/dist/lib/esm/process-capture.d.mts +83 -0
- package/dist/lib/esm/process-capture.mjs +38 -0
- package/dist/lib/esm/process-exit-message.d.mts +37 -3
- package/dist/lib/esm/process-exit-message.mjs +13 -8
- package/dist/lib/esm/process-liveness.d.mts +18 -0
- package/dist/lib/esm/process-liveness.mjs +17 -0
- package/dist/lib/esm/run-version-matrix.d.mts +1 -1
- package/dist/lib/esm/run-version-matrix.mjs +1 -1
- package/dist/lib/esm/teardown-verdict.d.mts +69 -0
- package/dist/lib/esm/teardown-verdict.mjs +28 -0
- package/dist/lib/esm/temporary-vault.d.mts +47 -5
- package/dist/lib/esm/temporary-vault.mjs +43 -8
- package/dist/lib/esm/transport-appium.d.mts +53 -3
- package/dist/lib/esm/transport-appium.mjs +108 -17
- package/dist/lib/esm/transport-desktop-cdp.d.mts +99 -0
- package/dist/lib/esm/transport-desktop-cdp.mjs +202 -7
- package/dist/lib/esm/transport-factory.mjs +995 -138
- package/dist/lib/esm/transport-options.d.mts +131 -12
- package/dist/lib/esm/transport-options.mjs +9 -2
- package/dist/lib/esm/transport.d.mts +7 -1
- package/dist/lib/esm/vault-plugin-install.d.mts +64 -0
- package/dist/lib/esm/vault-plugin-install.mjs +20 -0
- package/dist/lib/esm/vault-teardown-verdict.d.mts +57 -0
- package/dist/lib/esm/vault-teardown-verdict.mjs +18 -0
- package/dist/lib/esm/version-matrix.d.mts +2 -2
- package/dist/lib/esm/version-matrix.mjs +1 -1
- package/dist/lib/esm/webview-cdp.d.mts +5 -1
- package/dist/lib/esm/webview-cdp.mjs +6 -7
- package/package.json +24 -23
- package/dist/lib/cjs/native-dialog-monitor.cjs +0 -192
- package/dist/lib/cjs/native-dialog-monitor.d.cts +0 -66
- package/dist/lib/cjs/obsidian-namespace.cjs +0 -17
- package/dist/lib/cjs/obsidian-namespace.d.cts +0 -128
- package/dist/lib/esm/native-dialog-monitor.d.mts +0 -66
- package/dist/lib/esm/native-dialog-monitor.mjs +0 -158
- package/dist/lib/esm/obsidian-namespace.d.mts +0 -128
- package/dist/lib/esm/obsidian-namespace.mjs +0 -1
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file
|
|
3
|
+
*
|
|
4
|
+
* Pure helpers for tracking how far Obsidian Mobile has got through its startup
|
|
5
|
+
* after `location.reload()`, and for describing where it stalled when a budget
|
|
6
|
+
* runs out.
|
|
7
|
+
*
|
|
8
|
+
* Startup is watched as a **ladder of milestones**, not a single boolean,
|
|
9
|
+
* because the two halves of it cost wildly different amounts of time and only
|
|
10
|
+
* one of them is Obsidian's fault. Reaching `globalThis.app` is the app cold
|
|
11
|
+
* start — the WebView reloading, the guest still churning — and on a cold or
|
|
12
|
+
* contended emulator it can take minutes. Everything after it is Obsidian
|
|
13
|
+
* opening the vault and loading plugins, which **L19** measured at ~1s (≤8.4s
|
|
14
|
+
* under 12-core + disk + memory stress). Charging both to one 90s wall clock is
|
|
15
|
+
* what made a first run after a machine restart fail by design, so the transport
|
|
16
|
+
* runs them as two budgets and uses these helpers to tell them apart.
|
|
17
|
+
*
|
|
18
|
+
* Kept separate from the integration-only `transport-appium` (excluded from unit
|
|
19
|
+
* tests) so the classification and message formatting stay unit-testable — the
|
|
20
|
+
* polling itself needs a real device.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* How far Obsidian has got through its startup, as seen from one WebView probe.
|
|
24
|
+
*
|
|
25
|
+
* Ordered from least to most advanced; {@link compareAppStartupMilestones}
|
|
26
|
+
* relies on that order.
|
|
27
|
+
*/
|
|
28
|
+
export type AppStartupMilestone = 'layout-ready' | 'no-app' | 'no-webview' | 'no-workspace' | 'workspace-not-ready';
|
|
29
|
+
/**
|
|
30
|
+
* Which of the two startup budgets was being spent when it ran out.
|
|
31
|
+
*/
|
|
32
|
+
export type AppStartupPhase = 'app-start' | 'layout-ready';
|
|
33
|
+
/**
|
|
34
|
+
* Parameters for {@link buildStartupTimeoutMessage}.
|
|
35
|
+
*/
|
|
36
|
+
export interface BuildStartupTimeoutMessageParams {
|
|
37
|
+
/**
|
|
38
|
+
How long this phase's budget had been spent when it ran out.
|
|
39
|
+
*/
|
|
40
|
+
readonly elapsedInMilliseconds: number;
|
|
41
|
+
/**
|
|
42
|
+
The furthest milestone reached before the budget ran out.
|
|
43
|
+
*/
|
|
44
|
+
readonly milestone: AppStartupMilestone;
|
|
45
|
+
/**
|
|
46
|
+
The phase whose budget ran out.
|
|
47
|
+
*/
|
|
48
|
+
readonly phase: AppStartupPhase;
|
|
49
|
+
/**
|
|
50
|
+
How many probes were made during the phase.
|
|
51
|
+
*/
|
|
52
|
+
readonly pollCount: number;
|
|
53
|
+
/**
|
|
54
|
+
The slowest single probe round-trip observed during the phase.
|
|
55
|
+
*/
|
|
56
|
+
readonly slowestRoundTripInMilliseconds: number;
|
|
57
|
+
/**
|
|
58
|
+
The budget that ran out.
|
|
59
|
+
*/
|
|
60
|
+
readonly timeoutInMilliseconds: number;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The raw shape a WebView startup probe reports back.
|
|
64
|
+
*
|
|
65
|
+
* Mirrors what the injected probe function can observe without importing
|
|
66
|
+
* anything: whether the global `app` object exists yet, whether its `workspace`
|
|
67
|
+
* does, and whether that workspace has finished laying out.
|
|
68
|
+
*/
|
|
69
|
+
export interface StartupProbeResult {
|
|
70
|
+
/**
|
|
71
|
+
Whether `globalThis.app` is defined.
|
|
72
|
+
*/
|
|
73
|
+
readonly hasApp: boolean;
|
|
74
|
+
/**
|
|
75
|
+
Whether `app.workspace` is defined.
|
|
76
|
+
*/
|
|
77
|
+
readonly hasWorkspace: boolean;
|
|
78
|
+
/**
|
|
79
|
+
Whether `app.workspace.layoutReady` is truthy.
|
|
80
|
+
*/
|
|
81
|
+
readonly isLayoutReady: boolean;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Builds the diagnostic message for a startup budget that ran out.
|
|
85
|
+
*
|
|
86
|
+
* It names the milestone actually reached, the poll count and the slowest probe
|
|
87
|
+
* round-trip, because those three together separate the failure modes **L19**
|
|
88
|
+
* could not tell apart from the old message: a genuine Obsidian slowdown shows
|
|
89
|
+
* many fast polls stalled at one milestone, whereas a contended guest shows a
|
|
90
|
+
* handful of polls each taking tens of seconds.
|
|
91
|
+
*
|
|
92
|
+
* @param params - The phase, the milestone reached, and the timing evidence.
|
|
93
|
+
* @returns A human-readable error message.
|
|
94
|
+
*/
|
|
95
|
+
export declare function buildStartupTimeoutMessage(params: BuildStartupTimeoutMessageParams): string;
|
|
96
|
+
/**
|
|
97
|
+
* Reports whether the app-start phase is satisfied at this milestone.
|
|
98
|
+
*
|
|
99
|
+
* @param milestone - The milestone the latest probe reported.
|
|
100
|
+
* @returns `true` once `globalThis.app` exists, so the layout-ready budget may start.
|
|
101
|
+
*/
|
|
102
|
+
export declare function checkAppStarted(milestone: AppStartupMilestone): boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Reports whether the layout-ready phase is satisfied at this milestone.
|
|
105
|
+
*
|
|
106
|
+
* @param milestone - The milestone the latest probe reported.
|
|
107
|
+
* @returns `true` once the workspace has finished laying out.
|
|
108
|
+
*/
|
|
109
|
+
export declare function checkLayoutReady(milestone: AppStartupMilestone): boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Turns a WebView probe into a milestone.
|
|
112
|
+
*
|
|
113
|
+
* A probe that could not run at all — `undefined`, because `browser.execute()`
|
|
114
|
+
* threw while the page was mid-reload — is the least advanced milestone rather
|
|
115
|
+
* than an error: during a reload it is the expected reading.
|
|
116
|
+
*
|
|
117
|
+
* @param probeResult - What the probe reported, or `undefined` when it threw.
|
|
118
|
+
* @returns The milestone that reading represents.
|
|
119
|
+
*/
|
|
120
|
+
export declare function classifyAppStartupProbe(probeResult: StartupProbeResult | undefined): AppStartupMilestone;
|
|
121
|
+
/**
|
|
122
|
+
* Orders two milestones on the startup ladder.
|
|
123
|
+
*
|
|
124
|
+
* @param left - The first milestone.
|
|
125
|
+
* @param right - The second milestone.
|
|
126
|
+
* @returns A negative number when `left` is less advanced, `0` when equal, a positive number when more advanced.
|
|
127
|
+
*/
|
|
128
|
+
export declare function compareAppStartupMilestones(left: AppStartupMilestone, right: AppStartupMilestone): number;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const MILESTONE_ORDER = [
|
|
2
|
+
"no-webview",
|
|
3
|
+
"no-app",
|
|
4
|
+
"no-workspace",
|
|
5
|
+
"workspace-not-ready",
|
|
6
|
+
"layout-ready"
|
|
7
|
+
];
|
|
8
|
+
const APP_STARTED_MILESTONE = "no-workspace";
|
|
9
|
+
const MILESTONE_DESCRIPTIONS = {
|
|
10
|
+
"layout-ready": "the workspace finished laying out",
|
|
11
|
+
"no-app": "the WebView answered, but `globalThis.app` never appeared",
|
|
12
|
+
"no-webview": "the WebView never answered a single probe",
|
|
13
|
+
"no-workspace": "`globalThis.app` appeared, but `app.workspace` never did",
|
|
14
|
+
"workspace-not-ready": "`app.workspace` exists, but `layoutReady` never became true"
|
|
15
|
+
};
|
|
16
|
+
const PHASE_DESCRIPTIONS = {
|
|
17
|
+
"app-start": "Obsidian Mobile did not finish starting",
|
|
18
|
+
"layout-ready": "Obsidian layout did not become ready"
|
|
19
|
+
};
|
|
20
|
+
function buildStartupTimeoutMessage(params) {
|
|
21
|
+
const {
|
|
22
|
+
elapsedInMilliseconds,
|
|
23
|
+
milestone,
|
|
24
|
+
phase,
|
|
25
|
+
pollCount,
|
|
26
|
+
slowestRoundTripInMilliseconds,
|
|
27
|
+
timeoutInMilliseconds
|
|
28
|
+
} = params;
|
|
29
|
+
return `${PHASE_DESCRIPTIONS[phase]} within ${String(timeoutInMilliseconds)}ms (elapsed ${String(elapsedInMilliseconds)}ms). Furthest progress: ${MILESTONE_DESCRIPTIONS[milestone]}. Probed ${String(pollCount)} time(s), slowest round-trip ${String(slowestRoundTripInMilliseconds)}ms. A handful of probes each taking tens of seconds means a contended guest, not a slow Obsidian \u2014 let the emulator go idle before the run, or raise \`deviceIdleTimeoutInMilliseconds\`.`;
|
|
30
|
+
}
|
|
31
|
+
function checkAppStarted(milestone) {
|
|
32
|
+
return compareAppStartupMilestones(milestone, APP_STARTED_MILESTONE) >= 0;
|
|
33
|
+
}
|
|
34
|
+
function checkLayoutReady(milestone) {
|
|
35
|
+
return milestone === "layout-ready";
|
|
36
|
+
}
|
|
37
|
+
function classifyAppStartupProbe(probeResult) {
|
|
38
|
+
if (!probeResult) {
|
|
39
|
+
return "no-webview";
|
|
40
|
+
}
|
|
41
|
+
if (!probeResult.hasApp) {
|
|
42
|
+
return "no-app";
|
|
43
|
+
}
|
|
44
|
+
if (!probeResult.hasWorkspace) {
|
|
45
|
+
return "no-workspace";
|
|
46
|
+
}
|
|
47
|
+
return probeResult.isLayoutReady ? "layout-ready" : "workspace-not-ready";
|
|
48
|
+
}
|
|
49
|
+
function compareAppStartupMilestones(left, right) {
|
|
50
|
+
return MILESTONE_ORDER.indexOf(left) - MILESTONE_ORDER.indexOf(right);
|
|
51
|
+
}
|
|
52
|
+
export {
|
|
53
|
+
buildStartupTimeoutMessage,
|
|
54
|
+
checkAppStarted,
|
|
55
|
+
checkLayoutReady,
|
|
56
|
+
classifyAppStartupProbe,
|
|
57
|
+
compareAppStartupMilestones
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2FwcC1zdGFydHVwLXByb2dyZXNzLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBmaWxlXG4gKlxuICogUHVyZSBoZWxwZXJzIGZvciB0cmFja2luZyBob3cgZmFyIE9ic2lkaWFuIE1vYmlsZSBoYXMgZ290IHRocm91Z2ggaXRzIHN0YXJ0dXBcbiAqIGFmdGVyIGBsb2NhdGlvbi5yZWxvYWQoKWAsIGFuZCBmb3IgZGVzY3JpYmluZyB3aGVyZSBpdCBzdGFsbGVkIHdoZW4gYSBidWRnZXRcbiAqIHJ1bnMgb3V0LlxuICpcbiAqIFN0YXJ0dXAgaXMgd2F0Y2hlZCBhcyBhICoqbGFkZGVyIG9mIG1pbGVzdG9uZXMqKiwgbm90IGEgc2luZ2xlIGJvb2xlYW4sXG4gKiBiZWNhdXNlIHRoZSB0d28gaGFsdmVzIG9mIGl0IGNvc3Qgd2lsZGx5IGRpZmZlcmVudCBhbW91bnRzIG9mIHRpbWUgYW5kIG9ubHlcbiAqIG9uZSBvZiB0aGVtIGlzIE9ic2lkaWFuJ3MgZmF1bHQuIFJlYWNoaW5nIGBnbG9iYWxUaGlzLmFwcGAgaXMgdGhlIGFwcCBjb2xkXG4gKiBzdGFydCBcdTIwMTQgdGhlIFdlYlZpZXcgcmVsb2FkaW5nLCB0aGUgZ3Vlc3Qgc3RpbGwgY2h1cm5pbmcgXHUyMDE0IGFuZCBvbiBhIGNvbGQgb3JcbiAqIGNvbnRlbmRlZCBlbXVsYXRvciBpdCBjYW4gdGFrZSBtaW51dGVzLiBFdmVyeXRoaW5nIGFmdGVyIGl0IGlzIE9ic2lkaWFuXG4gKiBvcGVuaW5nIHRoZSB2YXVsdCBhbmQgbG9hZGluZyBwbHVnaW5zLCB3aGljaCAqKkwxOSoqIG1lYXN1cmVkIGF0IH4xcyAoXHUyMjY0OC40c1xuICogdW5kZXIgMTItY29yZSArIGRpc2sgKyBtZW1vcnkgc3RyZXNzKS4gQ2hhcmdpbmcgYm90aCB0byBvbmUgOTBzIHdhbGwgY2xvY2sgaXNcbiAqIHdoYXQgbWFkZSBhIGZpcnN0IHJ1biBhZnRlciBhIG1hY2hpbmUgcmVzdGFydCBmYWlsIGJ5IGRlc2lnbiwgc28gdGhlIHRyYW5zcG9ydFxuICogcnVucyB0aGVtIGFzIHR3byBidWRnZXRzIGFuZCB1c2VzIHRoZXNlIGhlbHBlcnMgdG8gdGVsbCB0aGVtIGFwYXJ0LlxuICpcbiAqIEtlcHQgc2VwYXJhdGUgZnJvbSB0aGUgaW50ZWdyYXRpb24tb25seSBgdHJhbnNwb3J0LWFwcGl1bWAgKGV4Y2x1ZGVkIGZyb20gdW5pdFxuICogdGVzdHMpIHNvIHRoZSBjbGFzc2lmaWNhdGlvbiBhbmQgbWVzc2FnZSBmb3JtYXR0aW5nIHN0YXkgdW5pdC10ZXN0YWJsZSBcdTIwMTQgdGhlXG4gKiBwb2xsaW5nIGl0c2VsZiBuZWVkcyBhIHJlYWwgZGV2aWNlLlxuICovXG5cbi8qKlxuICogSG93IGZhciBPYnNpZGlhbiBoYXMgZ290IHRocm91Z2ggaXRzIHN0YXJ0dXAsIGFzIHNlZW4gZnJvbSBvbmUgV2ViVmlldyBwcm9iZS5cbiAqXG4gKiBPcmRlcmVkIGZyb20gbGVhc3QgdG8gbW9zdCBhZHZhbmNlZDsge0BsaW5rIGNvbXBhcmVBcHBTdGFydHVwTWlsZXN0b25lc31cbiAqIHJlbGllcyBvbiB0aGF0IG9yZGVyLlxuICovXG5leHBvcnQgdHlwZSBBcHBTdGFydHVwTWlsZXN0b25lID1cbiAgfCAnbGF5b3V0LXJlYWR5J1xuICB8ICduby1hcHAnXG4gIHwgJ25vLXdlYnZpZXcnXG4gIHwgJ25vLXdvcmtzcGFjZSdcbiAgfCAnd29ya3NwYWNlLW5vdC1yZWFkeSc7XG5cbi8qKlxuICogV2hpY2ggb2YgdGhlIHR3byBzdGFydHVwIGJ1ZGdldHMgd2FzIGJlaW5nIHNwZW50IHdoZW4gaXQgcmFuIG91dC5cbiAqL1xuZXhwb3J0IHR5cGUgQXBwU3RhcnR1cFBoYXNlID0gJ2FwcC1zdGFydCcgfCAnbGF5b3V0LXJlYWR5JztcblxuLyoqXG4gKiBQYXJhbWV0ZXJzIGZvciB7QGxpbmsgYnVpbGRTdGFydHVwVGltZW91dE1lc3NhZ2V9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEJ1aWxkU3RhcnR1cFRpbWVvdXRNZXNzYWdlUGFyYW1zIHtcbiAgLyoqXG4gIEhvdyBsb25nIHRoaXMgcGhhc2UncyBidWRnZXQgaGFkIGJlZW4gc3BlbnQgd2hlbiBpdCByYW4gb3V0LlxuICAgKi9cbiAgcmVhZG9ubHkgZWxhcHNlZEluTWlsbGlzZWNvbmRzOiBudW1iZXI7XG5cbiAgLyoqXG4gIFRoZSBmdXJ0aGVzdCBtaWxlc3RvbmUgcmVhY2hlZCBiZWZvcmUgdGhlIGJ1ZGdldCByYW4gb3V0LlxuICAgKi9cbiAgcmVhZG9ubHkgbWlsZXN0b25lOiBBcHBTdGFydHVwTWlsZXN0b25lO1xuXG4gIC8qKlxuICBUaGUgcGhhc2Ugd2hvc2UgYnVkZ2V0IHJhbiBvdXQuXG4gICAqL1xuICByZWFkb25seSBwaGFzZTogQXBwU3RhcnR1cFBoYXNlO1xuXG4gIC8qKlxuICBIb3cgbWFueSBwcm9iZXMgd2VyZSBtYWRlIGR1cmluZyB0aGUgcGhhc2UuXG4gICAqL1xuICByZWFkb25seSBwb2xsQ291bnQ6IG51bWJlcjtcblxuICAvKipcbiAgVGhlIHNsb3dlc3Qgc2luZ2xlIHByb2JlIHJvdW5kLXRyaXAgb2JzZXJ2ZWQgZHVyaW5nIHRoZSBwaGFzZS5cbiAgICovXG4gIHJlYWRvbmx5IHNsb3dlc3RSb3VuZFRyaXBJbk1pbGxpc2Vjb25kczogbnVtYmVyO1xuXG4gIC8qKlxuICBUaGUgYnVkZ2V0IHRoYXQgcmFuIG91dC5cbiAgICovXG4gIHJlYWRvbmx5IHRpbWVvdXRJbk1pbGxpc2Vjb25kczogbnVtYmVyO1xufVxuXG4vKipcbiAqIFRoZSByYXcgc2hhcGUgYSBXZWJWaWV3IHN0YXJ0dXAgcHJvYmUgcmVwb3J0cyBiYWNrLlxuICpcbiAqIE1pcnJvcnMgd2hhdCB0aGUgaW5qZWN0ZWQgcHJvYmUgZnVuY3Rpb24gY2FuIG9ic2VydmUgd2l0aG91dCBpbXBvcnRpbmdcbiAqIGFueXRoaW5nOiB3aGV0aGVyIHRoZSBnbG9iYWwgYGFwcGAgb2JqZWN0IGV4aXN0cyB5ZXQsIHdoZXRoZXIgaXRzIGB3b3Jrc3BhY2VgXG4gKiBkb2VzLCBhbmQgd2hldGhlciB0aGF0IHdvcmtzcGFjZSBoYXMgZmluaXNoZWQgbGF5aW5nIG91dC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdGFydHVwUHJvYmVSZXN1bHQge1xuICAvKipcbiAgV2hldGhlciBgZ2xvYmFsVGhpcy5hcHBgIGlzIGRlZmluZWQuXG4gICAqL1xuICByZWFkb25seSBoYXNBcHA6IGJvb2xlYW47XG5cbiAgLyoqXG4gIFdoZXRoZXIgYGFwcC53b3Jrc3BhY2VgIGlzIGRlZmluZWQuXG4gICAqL1xuICByZWFkb25seSBoYXNXb3Jrc3BhY2U6IGJvb2xlYW47XG5cbiAgLyoqXG4gIFdoZXRoZXIgYGFwcC53b3Jrc3BhY2UubGF5b3V0UmVhZHlgIGlzIHRydXRoeS5cbiAgICovXG4gIHJlYWRvbmx5IGlzTGF5b3V0UmVhZHk6IGJvb2xlYW47XG59XG5cbi8qKlxuICogVGhlIG1pbGVzdG9uZSBsYWRkZXIsIGxlYXN0IHRvIG1vc3QgYWR2YW5jZWQuIFRoZSBpbmRleCBpbiB0aGlzIGFycmF5ICppcypcbiAqIHRoZSBvcmRlcmluZyB1c2VkIGJ5IHtAbGluayBjb21wYXJlQXBwU3RhcnR1cE1pbGVzdG9uZXN9LlxuICovXG5jb25zdCBNSUxFU1RPTkVfT1JERVI6IHJlYWRvbmx5IEFwcFN0YXJ0dXBNaWxlc3RvbmVbXSA9IFtcbiAgJ25vLXdlYnZpZXcnLFxuICAnbm8tYXBwJyxcbiAgJ25vLXdvcmtzcGFjZScsXG4gICd3b3Jrc3BhY2Utbm90LXJlYWR5JyxcbiAgJ2xheW91dC1yZWFkeSdcbl07XG5cbi8qKlxuICogVGhlIG1pbGVzdG9uZSBhdCB3aGljaCB0aGUgYXBwLXN0YXJ0IHBoYXNlIGlzIHNhdGlzZmllZDogYGdsb2JhbFRoaXMuYXBwYFxuICogZXhpc3RzLCBzbyB0aGUgV2ViVmlldyBoYXMgcmVsb2FkZWQgYW5kIE9ic2lkaWFuJ3Mgb3duIGJvb3QgaGFzIGJlZ3VuLiBXaGF0XG4gKiByZW1haW5zIGZyb20gaGVyZSBpcyBPYnNpZGlhbiB3b3JrLCB3aGljaCB0aGUgdGlnaHQgbGF5b3V0LXJlYWR5IGJ1ZGdldFxuICogY292ZXJzLlxuICovXG5jb25zdCBBUFBfU1RBUlRFRF9NSUxFU1RPTkU6IEFwcFN0YXJ0dXBNaWxlc3RvbmUgPSAnbm8td29ya3NwYWNlJztcblxuLyoqXG4gKiBIdW1hbi1yZWFkYWJsZSBkZXNjcmlwdGlvbnMgb2YgZWFjaCBtaWxlc3RvbmUsIHVzZWQgaW4gdGhlIHRpbWVvdXQgbWVzc2FnZSBzb1xuICogdGhlIGZhaWx1cmUgbmFtZXMgd2hhdCBuZXZlciBoYXBwZW5lZCBpbnN0ZWFkIG9mIG9ubHkgd2hhdCB3YXMgaG9wZWQgZm9yLlxuICovXG5jb25zdCBNSUxFU1RPTkVfREVTQ1JJUFRJT05TOiBSZWNvcmQ8QXBwU3RhcnR1cE1pbGVzdG9uZSwgc3RyaW5nPiA9IHtcbiAgJ2xheW91dC1yZWFkeSc6ICd0aGUgd29ya3NwYWNlIGZpbmlzaGVkIGxheWluZyBvdXQnLFxuICAnbm8tYXBwJzogJ3RoZSBXZWJWaWV3IGFuc3dlcmVkLCBidXQgYGdsb2JhbFRoaXMuYXBwYCBuZXZlciBhcHBlYXJlZCcsXG4gICduby13ZWJ2aWV3JzogJ3RoZSBXZWJWaWV3IG5ldmVyIGFuc3dlcmVkIGEgc2luZ2xlIHByb2JlJyxcbiAgJ25vLXdvcmtzcGFjZSc6ICdgZ2xvYmFsVGhpcy5hcHBgIGFwcGVhcmVkLCBidXQgYGFwcC53b3Jrc3BhY2VgIG5ldmVyIGRpZCcsXG4gICd3b3Jrc3BhY2Utbm90LXJlYWR5JzogJ2BhcHAud29ya3NwYWNlYCBleGlzdHMsIGJ1dCBgbGF5b3V0UmVhZHlgIG5ldmVyIGJlY2FtZSB0cnVlJ1xufTtcblxuLyoqXG4gKiBXaGF0IGVhY2ggcGhhc2Ugd2FzIHdhaXRpbmcgZm9yLCB1c2VkIGluIHRoZSB0aW1lb3V0IG1lc3NhZ2UuXG4gKi9cbmNvbnN0IFBIQVNFX0RFU0NSSVBUSU9OUzogUmVjb3JkPEFwcFN0YXJ0dXBQaGFzZSwgc3RyaW5nPiA9IHtcbiAgJ2FwcC1zdGFydCc6ICdPYnNpZGlhbiBNb2JpbGUgZGlkIG5vdCBmaW5pc2ggc3RhcnRpbmcnLFxuICAnbGF5b3V0LXJlYWR5JzogJ09ic2lkaWFuIGxheW91dCBkaWQgbm90IGJlY29tZSByZWFkeSdcbn07XG5cbi8qKlxuICogQnVpbGRzIHRoZSBkaWFnbm9zdGljIG1lc3NhZ2UgZm9yIGEgc3RhcnR1cCBidWRnZXQgdGhhdCByYW4gb3V0LlxuICpcbiAqIEl0IG5hbWVzIHRoZSBtaWxlc3RvbmUgYWN0dWFsbHkgcmVhY2hlZCwgdGhlIHBvbGwgY291bnQgYW5kIHRoZSBzbG93ZXN0IHByb2JlXG4gKiByb3VuZC10cmlwLCBiZWNhdXNlIHRob3NlIHRocmVlIHRvZ2V0aGVyIHNlcGFyYXRlIHRoZSBmYWlsdXJlIG1vZGVzICoqTDE5KipcbiAqIGNvdWxkIG5vdCB0ZWxsIGFwYXJ0IGZyb20gdGhlIG9sZCBtZXNzYWdlOiBhIGdlbnVpbmUgT2JzaWRpYW4gc2xvd2Rvd24gc2hvd3NcbiAqIG1hbnkgZmFzdCBwb2xscyBzdGFsbGVkIGF0IG9uZSBtaWxlc3RvbmUsIHdoZXJlYXMgYSBjb250ZW5kZWQgZ3Vlc3Qgc2hvd3MgYVxuICogaGFuZGZ1bCBvZiBwb2xscyBlYWNoIHRha2luZyB0ZW5zIG9mIHNlY29uZHMuXG4gKlxuICogQHBhcmFtIHBhcmFtcyAtIFRoZSBwaGFzZSwgdGhlIG1pbGVzdG9uZSByZWFjaGVkLCBhbmQgdGhlIHRpbWluZyBldmlkZW5jZS5cbiAqIEByZXR1cm5zIEEgaHVtYW4tcmVhZGFibGUgZXJyb3IgbWVzc2FnZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkU3RhcnR1cFRpbWVvdXRNZXNzYWdlKHBhcmFtczogQnVpbGRTdGFydHVwVGltZW91dE1lc3NhZ2VQYXJhbXMpOiBzdHJpbmcge1xuICBjb25zdCB7XG4gICAgZWxhcHNlZEluTWlsbGlzZWNvbmRzLFxuICAgIG1pbGVzdG9uZSxcbiAgICBwaGFzZSxcbiAgICBwb2xsQ291bnQsXG4gICAgc2xvd2VzdFJvdW5kVHJpcEluTWlsbGlzZWNvbmRzLFxuICAgIHRpbWVvdXRJbk1pbGxpc2Vjb25kc1xuICB9ID0gcGFyYW1zO1xuXG4gIHJldHVybiBgJHtQSEFTRV9ERVNDUklQVElPTlNbcGhhc2VdfSB3aXRoaW4gJHtTdHJpbmcodGltZW91dEluTWlsbGlzZWNvbmRzKX1tcyBgXG4gICAgKyBgKGVsYXBzZWQgJHtTdHJpbmcoZWxhcHNlZEluTWlsbGlzZWNvbmRzKX1tcykuIEZ1cnRoZXN0IHByb2dyZXNzOiAke01JTEVTVE9ORV9ERVNDUklQVElPTlNbbWlsZXN0b25lXX0uIGBcbiAgICArIGBQcm9iZWQgJHtTdHJpbmcocG9sbENvdW50KX0gdGltZShzKSwgc2xvd2VzdCByb3VuZC10cmlwICR7U3RyaW5nKHNsb3dlc3RSb3VuZFRyaXBJbk1pbGxpc2Vjb25kcyl9bXMuIGBcbiAgICArICdBIGhhbmRmdWwgb2YgcHJvYmVzIGVhY2ggdGFraW5nIHRlbnMgb2Ygc2Vjb25kcyBtZWFucyBhIGNvbnRlbmRlZCBndWVzdCwgbm90IGEgc2xvdyBPYnNpZGlhbiBcdTIwMTQgJ1xuICAgICsgJ2xldCB0aGUgZW11bGF0b3IgZ28gaWRsZSBiZWZvcmUgdGhlIHJ1biwgb3IgcmFpc2UgYGRldmljZUlkbGVUaW1lb3V0SW5NaWxsaXNlY29uZHNgLic7XG59XG5cbi8qKlxuICogUmVwb3J0cyB3aGV0aGVyIHRoZSBhcHAtc3RhcnQgcGhhc2UgaXMgc2F0aXNmaWVkIGF0IHRoaXMgbWlsZXN0b25lLlxuICpcbiAqIEBwYXJhbSBtaWxlc3RvbmUgLSBUaGUgbWlsZXN0b25lIHRoZSBsYXRlc3QgcHJvYmUgcmVwb3J0ZWQuXG4gKiBAcmV0dXJucyBgdHJ1ZWAgb25jZSBgZ2xvYmFsVGhpcy5hcHBgIGV4aXN0cywgc28gdGhlIGxheW91dC1yZWFkeSBidWRnZXQgbWF5IHN0YXJ0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2hlY2tBcHBTdGFydGVkKG1pbGVzdG9uZTogQXBwU3RhcnR1cE1pbGVzdG9uZSk6IGJvb2xlYW4ge1xuICByZXR1cm4gY29tcGFyZUFwcFN0YXJ0dXBNaWxlc3RvbmVzKG1pbGVzdG9uZSwgQVBQX1NUQVJURURfTUlMRVNUT05FKSA+PSAwO1xufVxuXG4vKipcbiAqIFJlcG9ydHMgd2hldGhlciB0aGUgbGF5b3V0LXJlYWR5IHBoYXNlIGlzIHNhdGlzZmllZCBhdCB0aGlzIG1pbGVzdG9uZS5cbiAqXG4gKiBAcGFyYW0gbWlsZXN0b25lIC0gVGhlIG1pbGVzdG9uZSB0aGUgbGF0ZXN0IHByb2JlIHJlcG9ydGVkLlxuICogQHJldHVybnMgYHRydWVgIG9uY2UgdGhlIHdvcmtzcGFjZSBoYXMgZmluaXNoZWQgbGF5aW5nIG91dC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNoZWNrTGF5b3V0UmVhZHkobWlsZXN0b25lOiBBcHBTdGFydHVwTWlsZXN0b25lKTogYm9vbGVhbiB7XG4gIHJldHVybiBtaWxlc3RvbmUgPT09ICdsYXlvdXQtcmVhZHknO1xufVxuXG4vKipcbiAqIFR1cm5zIGEgV2ViVmlldyBwcm9iZSBpbnRvIGEgbWlsZXN0b25lLlxuICpcbiAqIEEgcHJvYmUgdGhhdCBjb3VsZCBub3QgcnVuIGF0IGFsbCBcdTIwMTQgYHVuZGVmaW5lZGAsIGJlY2F1c2UgYGJyb3dzZXIuZXhlY3V0ZSgpYFxuICogdGhyZXcgd2hpbGUgdGhlIHBhZ2Ugd2FzIG1pZC1yZWxvYWQgXHUyMDE0IGlzIHRoZSBsZWFzdCBhZHZhbmNlZCBtaWxlc3RvbmUgcmF0aGVyXG4gKiB0aGFuIGFuIGVycm9yOiBkdXJpbmcgYSByZWxvYWQgaXQgaXMgdGhlIGV4cGVjdGVkIHJlYWRpbmcuXG4gKlxuICogQHBhcmFtIHByb2JlUmVzdWx0IC0gV2hhdCB0aGUgcHJvYmUgcmVwb3J0ZWQsIG9yIGB1bmRlZmluZWRgIHdoZW4gaXQgdGhyZXcuXG4gKiBAcmV0dXJucyBUaGUgbWlsZXN0b25lIHRoYXQgcmVhZGluZyByZXByZXNlbnRzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2xhc3NpZnlBcHBTdGFydHVwUHJvYmUocHJvYmVSZXN1bHQ6IFN0YXJ0dXBQcm9iZVJlc3VsdCB8IHVuZGVmaW5lZCk6IEFwcFN0YXJ0dXBNaWxlc3RvbmUge1xuICBpZiAoIXByb2JlUmVzdWx0KSB7XG4gICAgcmV0dXJuICduby13ZWJ2aWV3JztcbiAgfVxuICBpZiAoIXByb2JlUmVzdWx0Lmhhc0FwcCkge1xuICAgIHJldHVybiAnbm8tYXBwJztcbiAgfVxuICBpZiAoIXByb2JlUmVzdWx0Lmhhc1dvcmtzcGFjZSkge1xuICAgIHJldHVybiAnbm8td29ya3NwYWNlJztcbiAgfVxuICByZXR1cm4gcHJvYmVSZXN1bHQuaXNMYXlvdXRSZWFkeSA/ICdsYXlvdXQtcmVhZHknIDogJ3dvcmtzcGFjZS1ub3QtcmVhZHknO1xufVxuXG4vKipcbiAqIE9yZGVycyB0d28gbWlsZXN0b25lcyBvbiB0aGUgc3RhcnR1cCBsYWRkZXIuXG4gKlxuICogQHBhcmFtIGxlZnQgLSBUaGUgZmlyc3QgbWlsZXN0b25lLlxuICogQHBhcmFtIHJpZ2h0IC0gVGhlIHNlY29uZCBtaWxlc3RvbmUuXG4gKiBAcmV0dXJucyBBIG5lZ2F0aXZlIG51bWJlciB3aGVuIGBsZWZ0YCBpcyBsZXNzIGFkdmFuY2VkLCBgMGAgd2hlbiBlcXVhbCwgYSBwb3NpdGl2ZSBudW1iZXIgd2hlbiBtb3JlIGFkdmFuY2VkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY29tcGFyZUFwcFN0YXJ0dXBNaWxlc3RvbmVzKGxlZnQ6IEFwcFN0YXJ0dXBNaWxlc3RvbmUsIHJpZ2h0OiBBcHBTdGFydHVwTWlsZXN0b25lKTogbnVtYmVyIHtcbiAgcmV0dXJuIE1JTEVTVE9ORV9PUkRFUi5pbmRleE9mKGxlZnQpIC0gTUlMRVNUT05FX09SREVSLmluZGV4T2YocmlnaHQpO1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIkFBdUdBLE1BQU0sa0JBQWtEO0FBQUEsRUFDdEQ7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQ0Y7QUFRQSxNQUFNLHdCQUE2QztBQU1uRCxNQUFNLHlCQUE4RDtBQUFBLEVBQ2xFLGdCQUFnQjtBQUFBLEVBQ2hCLFVBQVU7QUFBQSxFQUNWLGNBQWM7QUFBQSxFQUNkLGdCQUFnQjtBQUFBLEVBQ2hCLHVCQUF1QjtBQUN6QjtBQUtBLE1BQU0scUJBQXNEO0FBQUEsRUFDMUQsYUFBYTtBQUFBLEVBQ2IsZ0JBQWdCO0FBQ2xCO0FBY08sU0FBUywyQkFBMkIsUUFBa0Q7QUFDM0YsUUFBTTtBQUFBLElBQ0o7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLEVBQ0YsSUFBSTtBQUVKLFNBQU8sR0FBRyxtQkFBbUIsS0FBSyxDQUFDLFdBQVcsT0FBTyxxQkFBcUIsQ0FBQyxlQUMzRCxPQUFPLHFCQUFxQixDQUFDLDJCQUEyQix1QkFBdUIsU0FBUyxDQUFDLFlBQzNGLE9BQU8sU0FBUyxDQUFDLGdDQUFnQyxPQUFPLDhCQUE4QixDQUFDO0FBR3ZHO0FBUU8sU0FBUyxnQkFBZ0IsV0FBeUM7QUFDdkUsU0FBTyw0QkFBNEIsV0FBVyxxQkFBcUIsS0FBSztBQUMxRTtBQVFPLFNBQVMsaUJBQWlCLFdBQXlDO0FBQ3hFLFNBQU8sY0FBYztBQUN2QjtBQVlPLFNBQVMsd0JBQXdCLGFBQWtFO0FBQ3hHLE1BQUksQ0FBQyxhQUFhO0FBQ2hCLFdBQU87QUFBQSxFQUNUO0FBQ0EsTUFBSSxDQUFDLFlBQVksUUFBUTtBQUN2QixXQUFPO0FBQUEsRUFDVDtBQUNBLE1BQUksQ0FBQyxZQUFZLGNBQWM7QUFDN0IsV0FBTztBQUFBLEVBQ1Q7QUFDQSxTQUFPLFlBQVksZ0JBQWdCLGlCQUFpQjtBQUN0RDtBQVNPLFNBQVMsNEJBQTRCLE1BQTJCLE9BQW9DO0FBQ3pHLFNBQU8sZ0JBQWdCLFFBQVEsSUFBSSxJQUFJLGdCQUFnQixRQUFRLEtBQUs7QUFDdEU7IiwKICAibmFtZXMiOiBbXQp9Cg==
|
|
@@ -33,6 +33,14 @@ export interface AppiumServerMarker {
|
|
|
33
33
|
When the server was started (`Date.now()` epoch milliseconds).
|
|
34
34
|
*/
|
|
35
35
|
readonly startedAtInMilliseconds: number;
|
|
36
|
+
/**
|
|
37
|
+
* When a run tried to stop this server and could not verify it exited
|
|
38
|
+
* (`Date.now()` epoch milliseconds), or `undefined` when no stop has failed.
|
|
39
|
+
*
|
|
40
|
+
* Its presence means the server is a **known-doomed leftover**: it was ours,
|
|
41
|
+
* we asked it to die, and it did not. See {@link recordAppiumServerStopAttempt}.
|
|
42
|
+
*/
|
|
43
|
+
readonly stopAttemptedAtInMilliseconds?: number | undefined;
|
|
36
44
|
}
|
|
37
45
|
/**
|
|
38
46
|
* Parameters for {@link writeAppiumServerMarker}.
|
|
@@ -72,6 +80,20 @@ export declare function clearAppiumServerMarker(port: number): void;
|
|
|
72
80
|
* @returns The marker, or `undefined` when there is none, it is unreadable, or it does not describe this port.
|
|
73
81
|
*/
|
|
74
82
|
export declare function readAppiumServerMarker(port: number): AppiumServerMarker | undefined;
|
|
83
|
+
/**
|
|
84
|
+
* Records that a run tried to stop the marked server and could not verify it
|
|
85
|
+
* exited — **instead of** clearing the marker.
|
|
86
|
+
*
|
|
87
|
+
* Clearing it would be the worst of both worlds: the leftover keeps serving, and
|
|
88
|
+
* the next run reads it as a foreign, user-managed server it must never touch
|
|
89
|
+
* (`checkIsHarnessOwnedAppiumServer` needs the marker to convict it). Keeping
|
|
90
|
+
* the marker, stamped, says exactly what is true — this is ours, and it outlived
|
|
91
|
+
* our teardown — which is what lets the next run refuse to adopt it and replace
|
|
92
|
+
* it instead.
|
|
93
|
+
*
|
|
94
|
+
* @param port - The Appium server port.
|
|
95
|
+
*/
|
|
96
|
+
export declare function recordAppiumServerStopAttempt(port: number): void;
|
|
75
97
|
/**
|
|
76
98
|
* Records the server this run just started, stamping it with the current time so
|
|
77
99
|
* a later run can report how long it has been up.
|
|
@@ -6,21 +6,15 @@ import {
|
|
|
6
6
|
} from "node:fs";
|
|
7
7
|
import { tmpdir } from "node:os";
|
|
8
8
|
import { join } from "node:path";
|
|
9
|
-
import process from "node:process";
|
|
10
9
|
import { log } from "./log.mjs";
|
|
10
|
+
import { checkIsProcessAlive } from "./process-liveness.mjs";
|
|
11
11
|
const MARKER_DIR_NAME = "obsidian-integration-testing";
|
|
12
12
|
const MARKER_FILE_SUFFIX = ".appium-server.json";
|
|
13
|
-
const PROCESS_EXISTENCE_PROBE_SIGNAL = 0;
|
|
14
13
|
function checkIsHarnessOwnedAppiumServer(marker) {
|
|
15
14
|
if (!marker) {
|
|
16
15
|
return false;
|
|
17
16
|
}
|
|
18
|
-
|
|
19
|
-
process.kill(marker.pid, PROCESS_EXISTENCE_PROBE_SIGNAL);
|
|
20
|
-
return true;
|
|
21
|
-
} catch (error) {
|
|
22
|
-
return getErrorCode(error) === "EPERM";
|
|
23
|
-
}
|
|
17
|
+
return checkIsProcessAlive(marker.pid);
|
|
24
18
|
}
|
|
25
19
|
function clearAppiumServerMarker(port) {
|
|
26
20
|
try {
|
|
@@ -38,21 +32,19 @@ function readAppiumServerMarker(port) {
|
|
|
38
32
|
}
|
|
39
33
|
return parseMarker(parsed, port);
|
|
40
34
|
}
|
|
35
|
+
function recordAppiumServerStopAttempt(port) {
|
|
36
|
+
const marker = readAppiumServerMarker(port);
|
|
37
|
+
if (!marker) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
writeMarker({ ...marker, stopAttemptedAtInMilliseconds: Date.now() });
|
|
41
|
+
}
|
|
41
42
|
function writeAppiumServerMarker(params) {
|
|
42
|
-
|
|
43
|
+
writeMarker({
|
|
43
44
|
pid: params.pid,
|
|
44
45
|
port: params.port,
|
|
45
46
|
startedAtInMilliseconds: Date.now()
|
|
46
|
-
};
|
|
47
|
-
try {
|
|
48
|
-
mkdirSync(getMarkerDirectory(), { recursive: true });
|
|
49
|
-
writeFileSync(getMarkerFilePath(params.port), JSON.stringify(marker));
|
|
50
|
-
} catch (error) {
|
|
51
|
-
log(`[appium-server-marker] Could not record the server on port ${String(params.port)}: ${getErrorMessage(error)}`);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
function getErrorCode(error) {
|
|
55
|
-
return typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0;
|
|
47
|
+
});
|
|
56
48
|
}
|
|
57
49
|
function getErrorMessage(error) {
|
|
58
50
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -68,16 +60,30 @@ function parseMarker(parsed, port) {
|
|
|
68
60
|
return void 0;
|
|
69
61
|
}
|
|
70
62
|
const record = parsed;
|
|
71
|
-
const { pid, port: markedPort, startedAtInMilliseconds } = record;
|
|
63
|
+
const { pid, port: markedPort, startedAtInMilliseconds, stopAttemptedAtInMilliseconds } = record;
|
|
72
64
|
if (typeof pid !== "number" || typeof startedAtInMilliseconds !== "number" || markedPort !== port) {
|
|
73
65
|
return void 0;
|
|
74
66
|
}
|
|
75
|
-
return {
|
|
67
|
+
return {
|
|
68
|
+
pid,
|
|
69
|
+
port,
|
|
70
|
+
startedAtInMilliseconds,
|
|
71
|
+
...typeof stopAttemptedAtInMilliseconds === "number" && { stopAttemptedAtInMilliseconds }
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function writeMarker(marker) {
|
|
75
|
+
try {
|
|
76
|
+
mkdirSync(getMarkerDirectory(), { recursive: true });
|
|
77
|
+
writeFileSync(getMarkerFilePath(marker.port), JSON.stringify(marker));
|
|
78
|
+
} catch (error) {
|
|
79
|
+
log(`[appium-server-marker] Could not record the server on port ${String(marker.port)}: ${getErrorMessage(error)}`);
|
|
80
|
+
}
|
|
76
81
|
}
|
|
77
82
|
export {
|
|
78
83
|
checkIsHarnessOwnedAppiumServer,
|
|
79
84
|
clearAppiumServerMarker,
|
|
80
85
|
readAppiumServerMarker,
|
|
86
|
+
recordAppiumServerStopAttempt,
|
|
81
87
|
writeAppiumServerMarker
|
|
82
88
|
};
|
|
83
|
-
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2FwcGl1bS1zZXJ2ZXItbWFya2VyLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBmaWxlXG4gKlxuICogUmVjb3JkcyB3aGljaCBBcHBpdW0gc2VydmVyIG9uIGEgcG9ydCB0aGlzIGhhcm5lc3Mgc3RhcnRlZCwgc28gYSBsYXRlciBydW5cbiAqIHRoYXQgZmluZHMgYSBzZXJ2ZXIgYWxyZWFkeSBsaXN0ZW5pbmcgY2FuIHRlbGwgKipwcm92ZW5hbmNlKio6IG9uZSBvZiBvdXIgb3duXG4gKiBzZXJ2ZXJzIGxlZnQgb3ZlciBmcm9tIGFuIGVhcmxpZXIgcnVuLCBvciBhIGZvcmVpZ24gb25lIHRoZSB1c2VyIG1hbmFnZXMuXG4gKlxuICogVGhlIHByZWZsaWdodCBhZG9wdHMgYW55IHNlcnZlciB0aGF0IGFuc3dlcnMgYC9zdGF0dXNgLCBhbmQgYWRvcHRpb24gaXMgdGhlXG4gKiByaWdodCBkZWZhdWx0IFx1MjAxNCBzdGFydGluZyBhIHNlY29uZCBzZXJ2ZXIgb24gYW4gb2NjdXBpZWQgcG9ydCBjYW5ub3Qgd29yay4gQnV0XG4gKiBhZG9wdGluZyBzaWxlbnRseSBtZWFucyBhIHdlZGdlZCBsZWZ0b3ZlciAoc2VlIGB3ZWRnZWQtYXBwaXVtLXNlcnZlci50c2ApIGlzXG4gKiBpbmRpc3Rpbmd1aXNoYWJsZSBmcm9tIGEgaGVhbHRoeSBzZXJ2ZXIsIGFuZCB0aGUgaGFybmVzcyBoYXMgbm8gYmFzaXMgb24gd2hpY2hcbiAqIHRvIGRlY2lkZSB3aGV0aGVyIHJlc3RhcnRpbmcgaXQgaXMgaXRzIGNhbGwgdG8gbWFrZS4gVGhlIG1hcmtlciBzdXBwbGllcyB0aGF0XG4gKiBiYXNpczogYSBzZXJ2ZXIgd2Ugc3RhcnRlZCBtYXkgYmUgcmVzdGFydGVkLCBhIGZvcmVpZ24gb25lIGlzIG9ubHkgZXZlclxuICogcmVwb3J0ZWQuXG4gKlxuICogVGhlIG1hcmtlciBpcyBhIHNtYWxsIEpTT04gc2VudGluZWwgbmV4dCB0byB0aGUgc2V0dXAgbG9jayAoYHNldHVwLWxvY2sudHNgKSxcbiAqIGtleWVkIGJ5IHBvcnQsIGFuZCBpcyBkZWxpYmVyYXRlbHkgdG9sZXJhbnQgXHUyMDE0IGEgbWlzc2luZywgdW5yZWFkYWJsZSwgb3JcbiAqIG1pc21hdGNoZWQgbWFya2VyIHNpbXBseSByZWFkcyBhcyBcIm5vdCBvdXJzXCIuXG4gKi9cblxuaW1wb3J0IHtcbiAgbWtkaXJTeW5jLFxuICByZWFkRmlsZVN5bmMsXG4gIHJtU3luYyxcbiAgd3JpdGVGaWxlU3luY1xufSBmcm9tICdub2RlOmZzJztcbmltcG9ydCB7IHRtcGRpciB9IGZyb20gJ25vZGU6b3MnO1xuaW1wb3J0IHsgam9pbiB9IGZyb20gJ25vZGU6cGF0aCc7XG5pbXBvcnQgcHJvY2VzcyBmcm9tICdub2RlOnByb2Nlc3MnO1xuXG5pbXBvcnQgeyBsb2cgfSBmcm9tICcuL2xvZy5tanMnO1xuXG5jb25zdCBNQVJLRVJfRElSX05BTUUgPSAnb2JzaWRpYW4taW50ZWdyYXRpb24tdGVzdGluZyc7XG5jb25zdCBNQVJLRVJfRklMRV9TVUZGSVggPSAnLmFwcGl1bS1zZXJ2ZXIuanNvbic7XG5jb25zdCBQUk9DRVNTX0VYSVNURU5DRV9QUk9CRV9TSUdOQUwgPSAwO1xuXG4vKipcbiAqIElkZW50aWZpZXMgdGhlIEFwcGl1bSBzZXJ2ZXIgdGhpcyBoYXJuZXNzIHN0YXJ0ZWQgb24gYSBwb3J0LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEFwcGl1bVNlcnZlck1hcmtlciB7XG4gIC8qKlxuICBQSUQgb2YgdGhlIHNwYXduZWQgc2VydmVyIHByb2Nlc3MgKHRoZSBzaGVsbCB3cmFwcGVyIHRoYXQgb3ducyB0aGUgc2VydmVyJ3MgcHJvY2VzcyB0cmVlKS5cbiAgICovXG4gIHJlYWRvbmx5IHBpZDogbnVtYmVyO1xuXG4gIC8qKlxuICBUaGUgcG9ydCB0aGUgc2VydmVyIHdhcyBzdGFydGVkIG9uLlxuICAgKi9cbiAgcmVhZG9ubHkgcG9ydDogbnVtYmVyO1xuXG4gIC8qKlxuICBXaGVuIHRoZSBzZXJ2ZXIgd2FzIHN0YXJ0ZWQgKGBEYXRlLm5vdygpYCBlcG9jaCBtaWxsaXNlY29uZHMpLlxuICAgKi9cbiAgcmVhZG9ubHkgc3RhcnRlZEF0SW5NaWxsaXNlY29uZHM6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBQYXJhbWV0ZXJzIGZvciB7QGxpbmsgd3JpdGVBcHBpdW1TZXJ2ZXJNYXJrZXJ9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFdyaXRlQXBwaXVtU2VydmVyTWFya2VyUGFyYW1zIHtcbiAgLyoqXG4gIFBJRCBvZiB0aGUgc3Bhd25lZCBzZXJ2ZXIgcHJvY2Vzcy5cbiAgICovXG4gIHJlYWRvbmx5IHBpZDogbnVtYmVyO1xuXG4gIC8qKlxuICBUaGUgcG9ydCB0aGUgc2VydmVyIHdhcyBzdGFydGVkIG9uLlxuICAgKi9cbiAgcmVhZG9ubHkgcG9ydDogbnVtYmVyO1xufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIHRoZSBtYXJrZWQgc2VydmVyIGlzIHN0aWxsIHJ1bm5pbmcsIHdoaWNoIGlzIHdoYXQgbWFrZXMgYW5cbiAqIGFkb3B0ZWQgc2VydmVyIG91cnMgdG8gcmVzdGFydC5cbiAqXG4gKiBBIGRlYWQgUElEIG1lYW5zIHRoZSBtYXJrZXIgb3V0bGl2ZWQgaXRzIHNlcnZlciwgc28gd2hhdGV2ZXIgYW5zd2VycyBvbiB0aGF0XG4gKiBwb3J0IG5vdyBpcyBzb21lYm9keSBlbHNlJ3MgXHUyMDE0IHRoZSBtYXJrZXIgcHJvdmVzIG5vdGhpbmcgYWJvdXQgaXQuXG4gKlxuICogQHBhcmFtIG1hcmtlciAtIFRoZSBtYXJrZXIgcmVhZCBmb3IgdGhlIHBvcnQsIG9yIGB1bmRlZmluZWRgIHdoZW4gdGhlcmUgaXMgbm9uZS5cbiAqIEByZXR1cm5zIGB0cnVlYCB3aGVuIGFuIGVhcmxpZXIgcnVuIG9mIHRoaXMgaGFybmVzcyBzdGFydGVkIHRoZSBzZXJ2ZXIgbm93IGxpc3RlbmluZy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNoZWNrSXNIYXJuZXNzT3duZWRBcHBpdW1TZXJ2ZXIobWFya2VyOiBBcHBpdW1TZXJ2ZXJNYXJrZXIgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgaWYgKCFtYXJrZXIpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICB0cnkge1xuICAgIHByb2Nlc3Mua2lsbChtYXJrZXIucGlkLCBQUk9DRVNTX0VYSVNURU5DRV9QUk9CRV9TSUdOQUwpO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgIC8vIGBFUEVSTWAgbWVhbnMgdGhlIHByb2Nlc3MgZXhpc3RzIGJ1dCBpcyBvd25lZCBieSBhbm90aGVyIHVzZXIgXHUyMDE0IHN0aWxsIGFsaXZlLlxuICAgIHJldHVybiBnZXRFcnJvckNvZGUoZXJyb3IpID09PSAnRVBFUk0nO1xuICB9XG59XG5cbi8qKlxuICogUmVtb3ZlcyB0aGUgbWFya2VyIGZvciBhIHBvcnQuIENhbGxlZCBvbmNlIHRoZSBtYXJrZWQgc2VydmVyIGhhcyBiZWVuIHN0b3BwZWQsXG4gKiBzbyBhIGxhdGVyIHJ1biBkb2VzIG5vdCBtaXN0YWtlIGEgcmVjeWNsZWQgUElEIGZvciBvdXIgc2VydmVyLlxuICpcbiAqIEBwYXJhbSBwb3J0IC0gVGhlIEFwcGl1bSBzZXJ2ZXIgcG9ydC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsZWFyQXBwaXVtU2VydmVyTWFya2VyKHBvcnQ6IG51bWJlcik6IHZvaWQge1xuICB0cnkge1xuICAgIHJtU3luYyhnZXRNYXJrZXJGaWxlUGF0aChwb3J0KSwgeyBmb3JjZTogdHJ1ZSB9KTtcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICBsb2coYFthcHBpdW0tc2VydmVyLW1hcmtlcl0gQ291bGQgbm90IHJlbW92ZSB0aGUgbWFya2VyIGZvciBwb3J0ICR7U3RyaW5nKHBvcnQpfTogJHtnZXRFcnJvck1lc3NhZ2UoZXJyb3IpfWApO1xuICB9XG59XG5cbi8qKlxuICogUmVhZHMgdGhlIG1hcmtlciBmb3IgYSBwb3J0LlxuICpcbiAqIEBwYXJhbSBwb3J0IC0gVGhlIEFwcGl1bSBzZXJ2ZXIgcG9ydC5cbiAqIEByZXR1cm5zIFRoZSBtYXJrZXIsIG9yIGB1bmRlZmluZWRgIHdoZW4gdGhlcmUgaXMgbm9uZSwgaXQgaXMgdW5yZWFkYWJsZSwgb3IgaXQgZG9lcyBub3QgZGVzY3JpYmUgdGhpcyBwb3J0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVhZEFwcGl1bVNlcnZlck1hcmtlcihwb3J0OiBudW1iZXIpOiBBcHBpdW1TZXJ2ZXJNYXJrZXIgfCB1bmRlZmluZWQge1xuICBsZXQgcGFyc2VkOiB1bmtub3duO1xuICB0cnkge1xuICAgIHBhcnNlZCA9IEpTT04ucGFyc2UocmVhZEZpbGVTeW5jKGdldE1hcmtlckZpbGVQYXRoKHBvcnQpLCAndXRmLTgnKSk7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICByZXR1cm4gcGFyc2VNYXJrZXIocGFyc2VkLCBwb3J0KTtcbn1cblxuLyoqXG4gKiBSZWNvcmRzIHRoZSBzZXJ2ZXIgdGhpcyBydW4ganVzdCBzdGFydGVkLCBzdGFtcGluZyBpdCB3aXRoIHRoZSBjdXJyZW50IHRpbWUgc29cbiAqIGEgbGF0ZXIgcnVuIGNhbiByZXBvcnQgaG93IGxvbmcgaXQgaGFzIGJlZW4gdXAuXG4gKlxuICogQHBhcmFtIHBhcmFtcyAtIFRoZSBzdGFydGVkIHNlcnZlcidzIFBJRCBhbmQgcG9ydC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdyaXRlQXBwaXVtU2VydmVyTWFya2VyKHBhcmFtczogV3JpdGVBcHBpdW1TZXJ2ZXJNYXJrZXJQYXJhbXMpOiB2b2lkIHtcbiAgY29uc3QgbWFya2VyOiBBcHBpdW1TZXJ2ZXJNYXJrZXIgPSB7XG4gICAgcGlkOiBwYXJhbXMucGlkLFxuICAgIHBvcnQ6IHBhcmFtcy5wb3J0LFxuICAgIHN0YXJ0ZWRBdEluTWlsbGlzZWNvbmRzOiBEYXRlLm5vdygpXG4gIH07XG5cbiAgdHJ5IHtcbiAgICBta2RpclN5bmMoZ2V0TWFya2VyRGlyZWN0b3J5KCksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgIHdyaXRlRmlsZVN5bmMoZ2V0TWFya2VyRmlsZVBhdGgocGFyYW1zLnBvcnQpLCBKU09OLnN0cmluZ2lmeShtYXJrZXIpKTtcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICBsb2coYFthcHBpdW0tc2VydmVyLW1hcmtlcl0gQ291bGQgbm90IHJlY29yZCB0aGUgc2VydmVyIG9uIHBvcnQgJHtTdHJpbmcocGFyYW1zLnBvcnQpfTogJHtnZXRFcnJvck1lc3NhZ2UoZXJyb3IpfWApO1xuICB9XG59XG5cbmZ1bmN0aW9uIGdldEVycm9yQ29kZShlcnJvcjogdW5rbm93bik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiB0eXBlb2YgZXJyb3IgPT09ICdvYmplY3QnICYmIGVycm9yICE9PSBudWxsICYmICdjb2RlJyBpbiBlcnJvciA/IFN0cmluZyhlcnJvci5jb2RlKSA6IHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gZ2V0RXJyb3JNZXNzYWdlKGVycm9yOiB1bmtub3duKTogc3RyaW5nIHtcbiAgcmV0dXJuIGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKTtcbn1cblxuZnVuY3Rpb24gZ2V0TWFya2VyRGlyZWN0b3J5KCk6IHN0cmluZyB7XG4gIHJldHVybiBqb2luKHRtcGRpcigpLCBNQVJLRVJfRElSX05BTUUpO1xufVxuXG5mdW5jdGlvbiBnZXRNYXJrZXJGaWxlUGF0aChwb3J0OiBudW1iZXIpOiBzdHJpbmcge1xuICByZXR1cm4gam9pbihnZXRNYXJrZXJEaXJlY3RvcnkoKSwgYCR7U3RyaW5nKHBvcnQpfSR7TUFSS0VSX0ZJTEVfU1VGRklYfWApO1xufVxuXG5mdW5jdGlvbiBwYXJzZU1hcmtlcihwYXJzZWQ6IHVua25vd24sIHBvcnQ6IG51bWJlcik6IEFwcGl1bVNlcnZlck1hcmtlciB8IHVuZGVmaW5lZCB7XG4gIGlmICh0eXBlb2YgcGFyc2VkICE9PSAnb2JqZWN0JyB8fCBwYXJzZWQgPT09IG51bGwpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgY29uc3QgcmVjb3JkID0gcGFyc2VkIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBjb25zdCB7IHBpZCwgcG9ydDogbWFya2VkUG9ydCwgc3RhcnRlZEF0SW5NaWxsaXNlY29uZHMgfSA9IHJlY29yZDtcblxuICBpZiAodHlwZW9mIHBpZCAhPT0gJ251bWJlcicgfHwgdHlwZW9mIHN0YXJ0ZWRBdEluTWlsbGlzZWNvbmRzICE9PSAnbnVtYmVyJyB8fCBtYXJrZWRQb3J0ICE9PSBwb3J0KSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHJldHVybiB7IHBpZCwgcG9ydCwgc3RhcnRlZEF0SW5NaWxsaXNlY29uZHMgfTtcbn1cbiJdLAogICJtYXBwaW5ncyI6ICJBQW9CQTtBQUFBLEVBQ0U7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxPQUNLO0FBQ1AsU0FBUyxjQUFjO0FBQ3ZCLFNBQVMsWUFBWTtBQUNyQixPQUFPLGFBQWE7QUFFcEIsU0FBUyxXQUFXO0FBRXBCLE1BQU0sa0JBQWtCO0FBQ3hCLE1BQU0scUJBQXFCO0FBQzNCLE1BQU0saUNBQWlDO0FBK0NoQyxTQUFTLGdDQUFnQyxRQUFpRDtBQUMvRixNQUFJLENBQUMsUUFBUTtBQUNYLFdBQU87QUFBQSxFQUNUO0FBRUEsTUFBSTtBQUNGLFlBQVEsS0FBSyxPQUFPLEtBQUssOEJBQThCO0FBQ3ZELFdBQU87QUFBQSxFQUNULFNBQVMsT0FBZ0I7QUFFdkIsV0FBTyxhQUFhLEtBQUssTUFBTTtBQUFBLEVBQ2pDO0FBQ0Y7QUFRTyxTQUFTLHdCQUF3QixNQUFvQjtBQUMxRCxNQUFJO0FBQ0YsV0FBTyxrQkFBa0IsSUFBSSxHQUFHLEVBQUUsT0FBTyxLQUFLLENBQUM7QUFBQSxFQUNqRCxTQUFTLE9BQWdCO0FBQ3ZCLFFBQUksK0RBQStELE9BQU8sSUFBSSxDQUFDLEtBQUssZ0JBQWdCLEtBQUssQ0FBQyxFQUFFO0FBQUEsRUFDOUc7QUFDRjtBQVFPLFNBQVMsdUJBQXVCLE1BQThDO0FBQ25GLE1BQUk7QUFDSixNQUFJO0FBQ0YsYUFBUyxLQUFLLE1BQU0sYUFBYSxrQkFBa0IsSUFBSSxHQUFHLE9BQU8sQ0FBQztBQUFBLEVBQ3BFLFFBQVE7QUFDTixXQUFPO0FBQUEsRUFDVDtBQUVBLFNBQU8sWUFBWSxRQUFRLElBQUk7QUFDakM7QUFRTyxTQUFTLHdCQUF3QixRQUE2QztBQUNuRixRQUFNLFNBQTZCO0FBQUEsSUFDakMsS0FBSyxPQUFPO0FBQUEsSUFDWixNQUFNLE9BQU87QUFBQSxJQUNiLHlCQUF5QixLQUFLLElBQUk7QUFBQSxFQUNwQztBQUVBLE1BQUk7QUFDRixjQUFVLG1CQUFtQixHQUFHLEVBQUUsV0FBVyxLQUFLLENBQUM7QUFDbkQsa0JBQWMsa0JBQWtCLE9BQU8sSUFBSSxHQUFHLEtBQUssVUFBVSxNQUFNLENBQUM7QUFBQSxFQUN0RSxTQUFTLE9BQWdCO0FBQ3ZCLFFBQUksOERBQThELE9BQU8sT0FBTyxJQUFJLENBQUMsS0FBSyxnQkFBZ0IsS0FBSyxDQUFDLEVBQUU7QUFBQSxFQUNwSDtBQUNGO0FBRUEsU0FBUyxhQUFhLE9BQW9DO0FBQ3hELFNBQU8sT0FBTyxVQUFVLFlBQVksVUFBVSxRQUFRLFVBQVUsUUFBUSxPQUFPLE1BQU0sSUFBSSxJQUFJO0FBQy9GO0FBRUEsU0FBUyxnQkFBZ0IsT0FBd0I7QUFDL0MsU0FBTyxpQkFBaUIsUUFBUSxNQUFNLFVBQVUsT0FBTyxLQUFLO0FBQzlEO0FBRUEsU0FBUyxxQkFBNkI7QUFDcEMsU0FBTyxLQUFLLE9BQU8sR0FBRyxlQUFlO0FBQ3ZDO0FBRUEsU0FBUyxrQkFBa0IsTUFBc0I7QUFDL0MsU0FBTyxLQUFLLG1CQUFtQixHQUFHLEdBQUcsT0FBTyxJQUFJLENBQUMsR0FBRyxrQkFBa0IsRUFBRTtBQUMxRTtBQUVBLFNBQVMsWUFBWSxRQUFpQixNQUE4QztBQUNsRixNQUFJLE9BQU8sV0FBVyxZQUFZLFdBQVcsTUFBTTtBQUNqRCxXQUFPO0FBQUEsRUFDVDtBQUVBLFFBQU0sU0FBUztBQUNmLFFBQU0sRUFBRSxLQUFLLE1BQU0sWUFBWSx3QkFBd0IsSUFBSTtBQUUzRCxNQUFJLE9BQU8sUUFBUSxZQUFZLE9BQU8sNEJBQTRCLFlBQVksZUFBZSxNQUFNO0FBQ2pHLFdBQU87QUFBQSxFQUNUO0FBRUEsU0FBTyxFQUFFLEtBQUssTUFBTSx3QkFBd0I7QUFDOUM7IiwKICAibmFtZXMiOiBbXQp9Cg==
|
|
89
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2FwcGl1bS1zZXJ2ZXItbWFya2VyLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBmaWxlXG4gKlxuICogUmVjb3JkcyB3aGljaCBBcHBpdW0gc2VydmVyIG9uIGEgcG9ydCB0aGlzIGhhcm5lc3Mgc3RhcnRlZCwgc28gYSBsYXRlciBydW5cbiAqIHRoYXQgZmluZHMgYSBzZXJ2ZXIgYWxyZWFkeSBsaXN0ZW5pbmcgY2FuIHRlbGwgKipwcm92ZW5hbmNlKio6IG9uZSBvZiBvdXIgb3duXG4gKiBzZXJ2ZXJzIGxlZnQgb3ZlciBmcm9tIGFuIGVhcmxpZXIgcnVuLCBvciBhIGZvcmVpZ24gb25lIHRoZSB1c2VyIG1hbmFnZXMuXG4gKlxuICogVGhlIHByZWZsaWdodCBhZG9wdHMgYW55IHNlcnZlciB0aGF0IGFuc3dlcnMgYC9zdGF0dXNgLCBhbmQgYWRvcHRpb24gaXMgdGhlXG4gKiByaWdodCBkZWZhdWx0IFx1MjAxNCBzdGFydGluZyBhIHNlY29uZCBzZXJ2ZXIgb24gYW4gb2NjdXBpZWQgcG9ydCBjYW5ub3Qgd29yay4gQnV0XG4gKiBhZG9wdGluZyBzaWxlbnRseSBtZWFucyBhIHdlZGdlZCBsZWZ0b3ZlciAoc2VlIGB3ZWRnZWQtYXBwaXVtLXNlcnZlci50c2ApIGlzXG4gKiBpbmRpc3Rpbmd1aXNoYWJsZSBmcm9tIGEgaGVhbHRoeSBzZXJ2ZXIsIGFuZCB0aGUgaGFybmVzcyBoYXMgbm8gYmFzaXMgb24gd2hpY2hcbiAqIHRvIGRlY2lkZSB3aGV0aGVyIHJlc3RhcnRpbmcgaXQgaXMgaXRzIGNhbGwgdG8gbWFrZS4gVGhlIG1hcmtlciBzdXBwbGllcyB0aGF0XG4gKiBiYXNpczogYSBzZXJ2ZXIgd2Ugc3RhcnRlZCBtYXkgYmUgcmVzdGFydGVkLCBhIGZvcmVpZ24gb25lIGlzIG9ubHkgZXZlclxuICogcmVwb3J0ZWQuXG4gKlxuICogVGhlIG1hcmtlciBpcyBhIHNtYWxsIEpTT04gc2VudGluZWwgbmV4dCB0byB0aGUgc2V0dXAgbG9jayAoYHNldHVwLWxvY2sudHNgKSxcbiAqIGtleWVkIGJ5IHBvcnQsIGFuZCBpcyBkZWxpYmVyYXRlbHkgdG9sZXJhbnQgXHUyMDE0IGEgbWlzc2luZywgdW5yZWFkYWJsZSwgb3JcbiAqIG1pc21hdGNoZWQgbWFya2VyIHNpbXBseSByZWFkcyBhcyBcIm5vdCBvdXJzXCIuXG4gKi9cblxuaW1wb3J0IHtcbiAgbWtkaXJTeW5jLFxuICByZWFkRmlsZVN5bmMsXG4gIHJtU3luYyxcbiAgd3JpdGVGaWxlU3luY1xufSBmcm9tICdub2RlOmZzJztcbmltcG9ydCB7IHRtcGRpciB9IGZyb20gJ25vZGU6b3MnO1xuaW1wb3J0IHsgam9pbiB9IGZyb20gJ25vZGU6cGF0aCc7XG5cbmltcG9ydCB7IGxvZyB9IGZyb20gJy4vbG9nLm1qcyc7XG5pbXBvcnQgeyBjaGVja0lzUHJvY2Vzc0FsaXZlIH0gZnJvbSAnLi9wcm9jZXNzLWxpdmVuZXNzLm1qcyc7XG5cbmNvbnN0IE1BUktFUl9ESVJfTkFNRSA9ICdvYnNpZGlhbi1pbnRlZ3JhdGlvbi10ZXN0aW5nJztcbmNvbnN0IE1BUktFUl9GSUxFX1NVRkZJWCA9ICcuYXBwaXVtLXNlcnZlci5qc29uJztcblxuLyoqXG4gKiBJZGVudGlmaWVzIHRoZSBBcHBpdW0gc2VydmVyIHRoaXMgaGFybmVzcyBzdGFydGVkIG9uIGEgcG9ydC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBcHBpdW1TZXJ2ZXJNYXJrZXIge1xuICAvKipcbiAgUElEIG9mIHRoZSBzcGF3bmVkIHNlcnZlciBwcm9jZXNzICh0aGUgc2hlbGwgd3JhcHBlciB0aGF0IG93bnMgdGhlIHNlcnZlcidzIHByb2Nlc3MgdHJlZSkuXG4gICAqL1xuICByZWFkb25seSBwaWQ6IG51bWJlcjtcblxuICAvKipcbiAgVGhlIHBvcnQgdGhlIHNlcnZlciB3YXMgc3RhcnRlZCBvbi5cbiAgICovXG4gIHJlYWRvbmx5IHBvcnQ6IG51bWJlcjtcblxuICAvKipcbiAgV2hlbiB0aGUgc2VydmVyIHdhcyBzdGFydGVkIChgRGF0ZS5ub3coKWAgZXBvY2ggbWlsbGlzZWNvbmRzKS5cbiAgICovXG4gIHJlYWRvbmx5IHN0YXJ0ZWRBdEluTWlsbGlzZWNvbmRzOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFdoZW4gYSBydW4gdHJpZWQgdG8gc3RvcCB0aGlzIHNlcnZlciBhbmQgY291bGQgbm90IHZlcmlmeSBpdCBleGl0ZWRcbiAgICogKGBEYXRlLm5vdygpYCBlcG9jaCBtaWxsaXNlY29uZHMpLCBvciBgdW5kZWZpbmVkYCB3aGVuIG5vIHN0b3AgaGFzIGZhaWxlZC5cbiAgICpcbiAgICogSXRzIHByZXNlbmNlIG1lYW5zIHRoZSBzZXJ2ZXIgaXMgYSAqKmtub3duLWRvb21lZCBsZWZ0b3ZlcioqOiBpdCB3YXMgb3VycyxcbiAgICogd2UgYXNrZWQgaXQgdG8gZGllLCBhbmQgaXQgZGlkIG5vdC4gU2VlIHtAbGluayByZWNvcmRBcHBpdW1TZXJ2ZXJTdG9wQXR0ZW1wdH0uXG4gICAqL1xuICByZWFkb25seSBzdG9wQXR0ZW1wdGVkQXRJbk1pbGxpc2Vjb25kcz86IG51bWJlciB8IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBQYXJhbWV0ZXJzIGZvciB7QGxpbmsgd3JpdGVBcHBpdW1TZXJ2ZXJNYXJrZXJ9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFdyaXRlQXBwaXVtU2VydmVyTWFya2VyUGFyYW1zIHtcbiAgLyoqXG4gIFBJRCBvZiB0aGUgc3Bhd25lZCBzZXJ2ZXIgcHJvY2Vzcy5cbiAgICovXG4gIHJlYWRvbmx5IHBpZDogbnVtYmVyO1xuXG4gIC8qKlxuICBUaGUgcG9ydCB0aGUgc2VydmVyIHdhcyBzdGFydGVkIG9uLlxuICAgKi9cbiAgcmVhZG9ubHkgcG9ydDogbnVtYmVyO1xufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIHRoZSBtYXJrZWQgc2VydmVyIGlzIHN0aWxsIHJ1bm5pbmcsIHdoaWNoIGlzIHdoYXQgbWFrZXMgYW5cbiAqIGFkb3B0ZWQgc2VydmVyIG91cnMgdG8gcmVzdGFydC5cbiAqXG4gKiBBIGRlYWQgUElEIG1lYW5zIHRoZSBtYXJrZXIgb3V0bGl2ZWQgaXRzIHNlcnZlciwgc28gd2hhdGV2ZXIgYW5zd2VycyBvbiB0aGF0XG4gKiBwb3J0IG5vdyBpcyBzb21lYm9keSBlbHNlJ3MgXHUyMDE0IHRoZSBtYXJrZXIgcHJvdmVzIG5vdGhpbmcgYWJvdXQgaXQuXG4gKlxuICogQHBhcmFtIG1hcmtlciAtIFRoZSBtYXJrZXIgcmVhZCBmb3IgdGhlIHBvcnQsIG9yIGB1bmRlZmluZWRgIHdoZW4gdGhlcmUgaXMgbm9uZS5cbiAqIEByZXR1cm5zIGB0cnVlYCB3aGVuIGFuIGVhcmxpZXIgcnVuIG9mIHRoaXMgaGFybmVzcyBzdGFydGVkIHRoZSBzZXJ2ZXIgbm93IGxpc3RlbmluZy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNoZWNrSXNIYXJuZXNzT3duZWRBcHBpdW1TZXJ2ZXIobWFya2VyOiBBcHBpdW1TZXJ2ZXJNYXJrZXIgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgaWYgKCFtYXJrZXIpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gY2hlY2tJc1Byb2Nlc3NBbGl2ZShtYXJrZXIucGlkKTtcbn1cblxuLyoqXG4gKiBSZW1vdmVzIHRoZSBtYXJrZXIgZm9yIGEgcG9ydC4gQ2FsbGVkIG9uY2UgdGhlIG1hcmtlZCBzZXJ2ZXIgaGFzIGJlZW4gc3RvcHBlZCxcbiAqIHNvIGEgbGF0ZXIgcnVuIGRvZXMgbm90IG1pc3Rha2UgYSByZWN5Y2xlZCBQSUQgZm9yIG91ciBzZXJ2ZXIuXG4gKlxuICogQHBhcmFtIHBvcnQgLSBUaGUgQXBwaXVtIHNlcnZlciBwb3J0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2xlYXJBcHBpdW1TZXJ2ZXJNYXJrZXIocG9ydDogbnVtYmVyKTogdm9pZCB7XG4gIHRyeSB7XG4gICAgcm1TeW5jKGdldE1hcmtlckZpbGVQYXRoKHBvcnQpLCB7IGZvcmNlOiB0cnVlIH0pO1xuICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgIGxvZyhgW2FwcGl1bS1zZXJ2ZXItbWFya2VyXSBDb3VsZCBub3QgcmVtb3ZlIHRoZSBtYXJrZXIgZm9yIHBvcnQgJHtTdHJpbmcocG9ydCl9OiAke2dldEVycm9yTWVzc2FnZShlcnJvcil9YCk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZWFkcyB0aGUgbWFya2VyIGZvciBhIHBvcnQuXG4gKlxuICogQHBhcmFtIHBvcnQgLSBUaGUgQXBwaXVtIHNlcnZlciBwb3J0LlxuICogQHJldHVybnMgVGhlIG1hcmtlciwgb3IgYHVuZGVmaW5lZGAgd2hlbiB0aGVyZSBpcyBub25lLCBpdCBpcyB1bnJlYWRhYmxlLCBvciBpdCBkb2VzIG5vdCBkZXNjcmliZSB0aGlzIHBvcnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWFkQXBwaXVtU2VydmVyTWFya2VyKHBvcnQ6IG51bWJlcik6IEFwcGl1bVNlcnZlck1hcmtlciB8IHVuZGVmaW5lZCB7XG4gIGxldCBwYXJzZWQ6IHVua25vd247XG4gIHRyeSB7XG4gICAgcGFyc2VkID0gSlNPTi5wYXJzZShyZWFkRmlsZVN5bmMoZ2V0TWFya2VyRmlsZVBhdGgocG9ydCksICd1dGYtOCcpKTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHJldHVybiBwYXJzZU1hcmtlcihwYXJzZWQsIHBvcnQpO1xufVxuXG4vKipcbiAqIFJlY29yZHMgdGhhdCBhIHJ1biB0cmllZCB0byBzdG9wIHRoZSBtYXJrZWQgc2VydmVyIGFuZCBjb3VsZCBub3QgdmVyaWZ5IGl0XG4gKiBleGl0ZWQgXHUyMDE0ICoqaW5zdGVhZCBvZioqIGNsZWFyaW5nIHRoZSBtYXJrZXIuXG4gKlxuICogQ2xlYXJpbmcgaXQgd291bGQgYmUgdGhlIHdvcnN0IG9mIGJvdGggd29ybGRzOiB0aGUgbGVmdG92ZXIga2VlcHMgc2VydmluZywgYW5kXG4gKiB0aGUgbmV4dCBydW4gcmVhZHMgaXQgYXMgYSBmb3JlaWduLCB1c2VyLW1hbmFnZWQgc2VydmVyIGl0IG11c3QgbmV2ZXIgdG91Y2hcbiAqIChgY2hlY2tJc0hhcm5lc3NPd25lZEFwcGl1bVNlcnZlcmAgbmVlZHMgdGhlIG1hcmtlciB0byBjb252aWN0IGl0KS4gS2VlcGluZ1xuICogdGhlIG1hcmtlciwgc3RhbXBlZCwgc2F5cyBleGFjdGx5IHdoYXQgaXMgdHJ1ZSBcdTIwMTQgdGhpcyBpcyBvdXJzLCBhbmQgaXQgb3V0bGl2ZWRcbiAqIG91ciB0ZWFyZG93biBcdTIwMTQgd2hpY2ggaXMgd2hhdCBsZXRzIHRoZSBuZXh0IHJ1biByZWZ1c2UgdG8gYWRvcHQgaXQgYW5kIHJlcGxhY2VcbiAqIGl0IGluc3RlYWQuXG4gKlxuICogQHBhcmFtIHBvcnQgLSBUaGUgQXBwaXVtIHNlcnZlciBwb3J0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVjb3JkQXBwaXVtU2VydmVyU3RvcEF0dGVtcHQocG9ydDogbnVtYmVyKTogdm9pZCB7XG4gIGNvbnN0IG1hcmtlciA9IHJlYWRBcHBpdW1TZXJ2ZXJNYXJrZXIocG9ydCk7XG4gIGlmICghbWFya2VyKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgd3JpdGVNYXJrZXIoeyAuLi5tYXJrZXIsIHN0b3BBdHRlbXB0ZWRBdEluTWlsbGlzZWNvbmRzOiBEYXRlLm5vdygpIH0pO1xufVxuXG4vKipcbiAqIFJlY29yZHMgdGhlIHNlcnZlciB0aGlzIHJ1biBqdXN0IHN0YXJ0ZWQsIHN0YW1waW5nIGl0IHdpdGggdGhlIGN1cnJlbnQgdGltZSBzb1xuICogYSBsYXRlciBydW4gY2FuIHJlcG9ydCBob3cgbG9uZyBpdCBoYXMgYmVlbiB1cC5cbiAqXG4gKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHN0YXJ0ZWQgc2VydmVyJ3MgUElEIGFuZCBwb3J0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gd3JpdGVBcHBpdW1TZXJ2ZXJNYXJrZXIocGFyYW1zOiBXcml0ZUFwcGl1bVNlcnZlck1hcmtlclBhcmFtcyk6IHZvaWQge1xuICB3cml0ZU1hcmtlcih7XG4gICAgcGlkOiBwYXJhbXMucGlkLFxuICAgIHBvcnQ6IHBhcmFtcy5wb3J0LFxuICAgIHN0YXJ0ZWRBdEluTWlsbGlzZWNvbmRzOiBEYXRlLm5vdygpXG4gIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRFcnJvck1lc3NhZ2UoZXJyb3I6IHVua25vd24pOiBzdHJpbmcge1xuICByZXR1cm4gZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpO1xufVxuXG5mdW5jdGlvbiBnZXRNYXJrZXJEaXJlY3RvcnkoKTogc3RyaW5nIHtcbiAgcmV0dXJuIGpvaW4odG1wZGlyKCksIE1BUktFUl9ESVJfTkFNRSk7XG59XG5cbmZ1bmN0aW9uIGdldE1hcmtlckZpbGVQYXRoKHBvcnQ6IG51bWJlcik6IHN0cmluZyB7XG4gIHJldHVybiBqb2luKGdldE1hcmtlckRpcmVjdG9yeSgpLCBgJHtTdHJpbmcocG9ydCl9JHtNQVJLRVJfRklMRV9TVUZGSVh9YCk7XG59XG5cbmZ1bmN0aW9uIHBhcnNlTWFya2VyKHBhcnNlZDogdW5rbm93biwgcG9ydDogbnVtYmVyKTogQXBwaXVtU2VydmVyTWFya2VyIHwgdW5kZWZpbmVkIHtcbiAgaWYgKHR5cGVvZiBwYXJzZWQgIT09ICdvYmplY3QnIHx8IHBhcnNlZCA9PT0gbnVsbCkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBjb25zdCByZWNvcmQgPSBwYXJzZWQgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGNvbnN0IHsgcGlkLCBwb3J0OiBtYXJrZWRQb3J0LCBzdGFydGVkQXRJbk1pbGxpc2Vjb25kcywgc3RvcEF0dGVtcHRlZEF0SW5NaWxsaXNlY29uZHMgfSA9IHJlY29yZDtcblxuICBpZiAodHlwZW9mIHBpZCAhPT0gJ251bWJlcicgfHwgdHlwZW9mIHN0YXJ0ZWRBdEluTWlsbGlzZWNvbmRzICE9PSAnbnVtYmVyJyB8fCBtYXJrZWRQb3J0ICE9PSBwb3J0KSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgcGlkLFxuICAgIHBvcnQsXG4gICAgc3RhcnRlZEF0SW5NaWxsaXNlY29uZHMsXG4gICAgLi4uKHR5cGVvZiBzdG9wQXR0ZW1wdGVkQXRJbk1pbGxpc2Vjb25kcyA9PT0gJ251bWJlcicgJiYgeyBzdG9wQXR0ZW1wdGVkQXRJbk1pbGxpc2Vjb25kcyB9KVxuICB9O1xufVxuXG5mdW5jdGlvbiB3cml0ZU1hcmtlcihtYXJrZXI6IEFwcGl1bVNlcnZlck1hcmtlcik6IHZvaWQge1xuICB0cnkge1xuICAgIG1rZGlyU3luYyhnZXRNYXJrZXJEaXJlY3RvcnkoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgd3JpdGVGaWxlU3luYyhnZXRNYXJrZXJGaWxlUGF0aChtYXJrZXIucG9ydCksIEpTT04uc3RyaW5naWZ5KG1hcmtlcikpO1xuICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgIGxvZyhgW2FwcGl1bS1zZXJ2ZXItbWFya2VyXSBDb3VsZCBub3QgcmVjb3JkIHRoZSBzZXJ2ZXIgb24gcG9ydCAke1N0cmluZyhtYXJrZXIucG9ydCl9OiAke2dldEVycm9yTWVzc2FnZShlcnJvcil9YCk7XG4gIH1cbn1cbiJdLAogICJtYXBwaW5ncyI6ICJBQW9CQTtBQUFBLEVBQ0U7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxPQUNLO0FBQ1AsU0FBUyxjQUFjO0FBQ3ZCLFNBQVMsWUFBWTtBQUVyQixTQUFTLFdBQVc7QUFDcEIsU0FBUywyQkFBMkI7QUFFcEMsTUFBTSxrQkFBa0I7QUFDeEIsTUFBTSxxQkFBcUI7QUF3RHBCLFNBQVMsZ0NBQWdDLFFBQWlEO0FBQy9GLE1BQUksQ0FBQyxRQUFRO0FBQ1gsV0FBTztBQUFBLEVBQ1Q7QUFFQSxTQUFPLG9CQUFvQixPQUFPLEdBQUc7QUFDdkM7QUFRTyxTQUFTLHdCQUF3QixNQUFvQjtBQUMxRCxNQUFJO0FBQ0YsV0FBTyxrQkFBa0IsSUFBSSxHQUFHLEVBQUUsT0FBTyxLQUFLLENBQUM7QUFBQSxFQUNqRCxTQUFTLE9BQWdCO0FBQ3ZCLFFBQUksK0RBQStELE9BQU8sSUFBSSxDQUFDLEtBQUssZ0JBQWdCLEtBQUssQ0FBQyxFQUFFO0FBQUEsRUFDOUc7QUFDRjtBQVFPLFNBQVMsdUJBQXVCLE1BQThDO0FBQ25GLE1BQUk7QUFDSixNQUFJO0FBQ0YsYUFBUyxLQUFLLE1BQU0sYUFBYSxrQkFBa0IsSUFBSSxHQUFHLE9BQU8sQ0FBQztBQUFBLEVBQ3BFLFFBQVE7QUFDTixXQUFPO0FBQUEsRUFDVDtBQUVBLFNBQU8sWUFBWSxRQUFRLElBQUk7QUFDakM7QUFlTyxTQUFTLDhCQUE4QixNQUFvQjtBQUNoRSxRQUFNLFNBQVMsdUJBQXVCLElBQUk7QUFDMUMsTUFBSSxDQUFDLFFBQVE7QUFDWDtBQUFBLEVBQ0Y7QUFFQSxjQUFZLEVBQUUsR0FBRyxRQUFRLCtCQUErQixLQUFLLElBQUksRUFBRSxDQUFDO0FBQ3RFO0FBUU8sU0FBUyx3QkFBd0IsUUFBNkM7QUFDbkYsY0FBWTtBQUFBLElBQ1YsS0FBSyxPQUFPO0FBQUEsSUFDWixNQUFNLE9BQU87QUFBQSxJQUNiLHlCQUF5QixLQUFLLElBQUk7QUFBQSxFQUNwQyxDQUFDO0FBQ0g7QUFFQSxTQUFTLGdCQUFnQixPQUF3QjtBQUMvQyxTQUFPLGlCQUFpQixRQUFRLE1BQU0sVUFBVSxPQUFPLEtBQUs7QUFDOUQ7QUFFQSxTQUFTLHFCQUE2QjtBQUNwQyxTQUFPLEtBQUssT0FBTyxHQUFHLGVBQWU7QUFDdkM7QUFFQSxTQUFTLGtCQUFrQixNQUFzQjtBQUMvQyxTQUFPLEtBQUssbUJBQW1CLEdBQUcsR0FBRyxPQUFPLElBQUksQ0FBQyxHQUFHLGtCQUFrQixFQUFFO0FBQzFFO0FBRUEsU0FBUyxZQUFZLFFBQWlCLE1BQThDO0FBQ2xGLE1BQUksT0FBTyxXQUFXLFlBQVksV0FBVyxNQUFNO0FBQ2pELFdBQU87QUFBQSxFQUNUO0FBRUEsUUFBTSxTQUFTO0FBQ2YsUUFBTSxFQUFFLEtBQUssTUFBTSxZQUFZLHlCQUF5Qiw4QkFBOEIsSUFBSTtBQUUxRixNQUFJLE9BQU8sUUFBUSxZQUFZLE9BQU8sNEJBQTRCLFlBQVksZUFBZSxNQUFNO0FBQ2pHLFdBQU87QUFBQSxFQUNUO0FBRUEsU0FBTztBQUFBLElBQ0w7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0EsR0FBSSxPQUFPLGtDQUFrQyxZQUFZLEVBQUUsOEJBQThCO0FBQUEsRUFDM0Y7QUFDRjtBQUVBLFNBQVMsWUFBWSxRQUFrQztBQUNyRCxNQUFJO0FBQ0YsY0FBVSxtQkFBbUIsR0FBRyxFQUFFLFdBQVcsS0FBSyxDQUFDO0FBQ25ELGtCQUFjLGtCQUFrQixPQUFPLElBQUksR0FBRyxLQUFLLFVBQVUsTUFBTSxDQUFDO0FBQUEsRUFDdEUsU0FBUyxPQUFnQjtBQUN2QixRQUFJLDhEQUE4RCxPQUFPLE9BQU8sSUFBSSxDQUFDLEtBQUssZ0JBQWdCLEtBQUssQ0FBQyxFQUFFO0FBQUEsRUFDcEg7QUFDRjsiLAogICJuYW1lcyI6IFtdCn0K
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file
|
|
3
|
+
*
|
|
4
|
+
* Pure classification of the AVD adoption probe — deciding, from what each
|
|
5
|
+
* connected device answered, whether this run may reuse one, must start its
|
|
6
|
+
* own emulator, or cannot safely do either.
|
|
7
|
+
*
|
|
8
|
+
* The probe (`adb -s <device> emu avd name`) used to discard its error and
|
|
9
|
+
* resolve `''`, so a call that **never answered** was indistinguishable from one
|
|
10
|
+
* that answered *"a different AVD"*. Both fell through to "start a new
|
|
11
|
+
* emulator", which collides with the emulator already serving that AVD:
|
|
12
|
+
*
|
|
13
|
+
* ```text
|
|
14
|
+
* 14:27:52.114 Checking existing devices for AVD "obsidian_test"... (connected: [emulator-5554])
|
|
15
|
+
* 14:27:57.170 AVD "obsidian_test" not found on any existing device, starting a new emulator...
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* 5.056s apart — exactly the probe's own timeout. The launch that followed hit
|
|
19
|
+
* `FATAL | Running multiple emulators with the same AVD is an experimental
|
|
20
|
+
* feature`, which the emulator writes to its own stdout. **A probe that never
|
|
21
|
+
* answered is not evidence that the answer is no** — the same distinction
|
|
22
|
+
* `adb-device-list.ts` draws between `offline` and absent, and the same one
|
|
23
|
+
* the connectivity probe draws between a failed dump and a missing network.
|
|
24
|
+
*
|
|
25
|
+
* Worse, the probe is asked its question precisely when the guest is least able
|
|
26
|
+
* to answer it — a wedged emulator times out every `adb` call — which is the
|
|
27
|
+
* condition under which a colliding launch does the most damage.
|
|
28
|
+
*
|
|
29
|
+
* Kept separate from the integration-only `transport-factory` (excluded from
|
|
30
|
+
* unit tests) so the classification stays unit-testable — the factory itself
|
|
31
|
+
* shells out to `adb`.
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* What one device answered when asked which AVD it is serving.
|
|
35
|
+
*
|
|
36
|
+
* `not-an-emulator` and `other-avd` are both legitimate skips; only
|
|
37
|
+
* `no-answer` is the silence that must never be read as one.
|
|
38
|
+
*/
|
|
39
|
+
export type AvdProbeOutcome = 'match' | 'no-answer' | 'not-an-emulator' | 'other-avd';
|
|
40
|
+
/**
|
|
41
|
+
* The run cannot tell whether the AVD is already running, so it must not launch.
|
|
42
|
+
*/
|
|
43
|
+
export interface AvdProbeRefuseVerdict {
|
|
44
|
+
/**
|
|
45
|
+
The devices that could not be read, and therefore cannot be ruled out as the AVD's holder.
|
|
46
|
+
*/
|
|
47
|
+
readonly unreadableDeviceIds: string[];
|
|
48
|
+
/**
|
|
49
|
+
Discriminant.
|
|
50
|
+
*/
|
|
51
|
+
readonly verdict: 'refuse';
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* One device's probe outcome.
|
|
55
|
+
*/
|
|
56
|
+
export interface AvdProbeResult {
|
|
57
|
+
/**
|
|
58
|
+
The device UDID, e.g. `emulator-5554`.
|
|
59
|
+
*/
|
|
60
|
+
readonly deviceId: string;
|
|
61
|
+
/**
|
|
62
|
+
What the device answered.
|
|
63
|
+
*/
|
|
64
|
+
readonly outcome: AvdProbeOutcome;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* The AVD is already running, on a device this run may adopt.
|
|
68
|
+
*/
|
|
69
|
+
export interface AvdProbeReuseVerdict {
|
|
70
|
+
/**
|
|
71
|
+
The device already serving the requested AVD.
|
|
72
|
+
*/
|
|
73
|
+
readonly deviceId: string;
|
|
74
|
+
/**
|
|
75
|
+
Discriminant.
|
|
76
|
+
*/
|
|
77
|
+
readonly verdict: 'reuse';
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Every device answered, none is serving the AVD, so launching cannot collide.
|
|
81
|
+
*/
|
|
82
|
+
export interface AvdProbeStartNewVerdict {
|
|
83
|
+
/**
|
|
84
|
+
Discriminant.
|
|
85
|
+
*/
|
|
86
|
+
readonly verdict: 'start-new';
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* What the run may do, given every device's probe outcome.
|
|
90
|
+
*/
|
|
91
|
+
export type AvdProbeVerdict = AvdProbeRefuseVerdict | AvdProbeReuseVerdict | AvdProbeStartNewVerdict;
|
|
92
|
+
/**
|
|
93
|
+
* Parameters for {@link buildUnreadableDevicesMessage}.
|
|
94
|
+
*/
|
|
95
|
+
export interface BuildUnreadableDevicesMessageParams {
|
|
96
|
+
/**
|
|
97
|
+
The AVD the run wanted.
|
|
98
|
+
*/
|
|
99
|
+
readonly avdName: string;
|
|
100
|
+
/**
|
|
101
|
+
The budget each probe attempt was given, in milliseconds.
|
|
102
|
+
*/
|
|
103
|
+
readonly probeTimeoutInMilliseconds: number;
|
|
104
|
+
/**
|
|
105
|
+
The devices that did not answer.
|
|
106
|
+
*/
|
|
107
|
+
readonly unreadableDeviceIds: readonly string[];
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Parameters for {@link classifyAvdProbe}.
|
|
111
|
+
*/
|
|
112
|
+
export interface ClassifyAvdProbeParams {
|
|
113
|
+
/**
|
|
114
|
+
The AVD the run wants.
|
|
115
|
+
*/
|
|
116
|
+
readonly avdName: string;
|
|
117
|
+
/**
|
|
118
|
+
The device that was probed.
|
|
119
|
+
*/
|
|
120
|
+
readonly deviceId: string;
|
|
121
|
+
/**
|
|
122
|
+
The AVD name the device answered, or `undefined` when it did not answer at all.
|
|
123
|
+
*/
|
|
124
|
+
readonly probedAvdName?: string | undefined;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Builds the summary line naming what each device answered.
|
|
128
|
+
*
|
|
129
|
+
* The old log printed only the conclusion (`not found on any existing device`),
|
|
130
|
+
* which is exactly the line that was wrong; printing the evidence next to it is
|
|
131
|
+
* what makes a bad conclusion visible without a second run.
|
|
132
|
+
*
|
|
133
|
+
* @param results - Every device's probe outcome.
|
|
134
|
+
* @returns The summary, or `no devices` when nothing was connected.
|
|
135
|
+
*/
|
|
136
|
+
export declare function buildAvdProbeSummary(results: readonly AvdProbeResult[]): string;
|
|
137
|
+
/**
|
|
138
|
+
* Builds the refusal message for devices that could not be read.
|
|
139
|
+
*
|
|
140
|
+
* Names the device, the AVD, the budget, the consequence and the recovery — the
|
|
141
|
+
* shape `teardown-verdict.ts` uses for its own warning, because a message that
|
|
142
|
+
* stops a run has to leave the reader able to unblock it.
|
|
143
|
+
*
|
|
144
|
+
* @param params - The AVD, the probe budget, and the devices that did not answer.
|
|
145
|
+
* @returns The refusal message.
|
|
146
|
+
*/
|
|
147
|
+
export declare function buildUnreadableDevicesMessage(params: BuildUnreadableDevicesMessageParams): string;
|
|
148
|
+
/**
|
|
149
|
+
* Decides whether a device can hold an AVD this run could collide with.
|
|
150
|
+
*
|
|
151
|
+
* @param deviceId - The device UDID to judge.
|
|
152
|
+
* @returns `true` for a locally started emulator, whose console this run can ask.
|
|
153
|
+
*/
|
|
154
|
+
export declare function checkIsEmulatorDeviceId(deviceId: string): boolean;
|
|
155
|
+
/**
|
|
156
|
+
* Classifies one device's probe.
|
|
157
|
+
*
|
|
158
|
+
* @param params - The AVD wanted, the device probed, and what it answered.
|
|
159
|
+
* @returns The outcome.
|
|
160
|
+
*/
|
|
161
|
+
export declare function classifyAvdProbe(params: ClassifyAvdProbeParams): AvdProbeOutcome;
|
|
162
|
+
/**
|
|
163
|
+
* Decides what the run may do, from every device's probe outcome.
|
|
164
|
+
*
|
|
165
|
+
* **A match wins over an unreadable sibling.** Once the requested AVD is found
|
|
166
|
+
* and reusable, an unrelated wedged device is somebody else's problem and must
|
|
167
|
+
* not block a run that has everything it needs — the same restraint
|
|
168
|
+
* `emulator-backend.ts` shows in never sweeping a `qemu*` it does not own. Only
|
|
169
|
+
* when nothing matched does silence become decisive, because only then would the
|
|
170
|
+
* run go on to launch.
|
|
171
|
+
*
|
|
172
|
+
* @param results - Every device's probe outcome.
|
|
173
|
+
* @returns The verdict.
|
|
174
|
+
*/
|
|
175
|
+
export declare function resolveAvdProbeVerdict(results: readonly AvdProbeResult[]): AvdProbeVerdict;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { assertNever } from "./type-guards.mjs";
|
|
2
|
+
const EMULATOR_DEVICE_ID_PATTERN = /^emulator-\d+$/;
|
|
3
|
+
function buildAvdProbeSummary(results) {
|
|
4
|
+
if (results.length === 0) {
|
|
5
|
+
return "no devices";
|
|
6
|
+
}
|
|
7
|
+
return results.map((result) => `${result.deviceId}=${result.outcome}`).join(", ");
|
|
8
|
+
}
|
|
9
|
+
function buildUnreadableDevicesMessage(params) {
|
|
10
|
+
const deviceList = params.unreadableDeviceIds.join(", ");
|
|
11
|
+
const isSingle = params.unreadableDeviceIds.length === 1;
|
|
12
|
+
const subject = isSingle ? `device ${deviceList}` : `devices ${deviceList}`;
|
|
13
|
+
const command = isSingle ? `adb -s ${deviceList} emu avd name` : "adb -s <device> emu avd name";
|
|
14
|
+
const holder = isSingle ? "it is" : "one of them is";
|
|
15
|
+
const remedy = isSingle ? "Kill the unresponsive device" : "Kill the unresponsive devices";
|
|
16
|
+
return `AVD "${params.avdName}": ${subject} did not answer \`${command}\` within ${String(params.probeTimeoutInMilliseconds)}ms (retried once), so this run cannot tell whether ${holder} already serving that AVD. Starting an emulator anyway would collide (\`FATAL | Running multiple emulators with the same AVD is an experimental feature\`), which the emulator reports only to its own stdout. ${remedy}, or run \`adb kill-server\`, then retry.`;
|
|
17
|
+
}
|
|
18
|
+
function checkIsEmulatorDeviceId(deviceId) {
|
|
19
|
+
return EMULATOR_DEVICE_ID_PATTERN.test(deviceId);
|
|
20
|
+
}
|
|
21
|
+
function classifyAvdProbe(params) {
|
|
22
|
+
if (!checkIsEmulatorDeviceId(params.deviceId)) {
|
|
23
|
+
return "not-an-emulator";
|
|
24
|
+
}
|
|
25
|
+
if (params.probedAvdName === void 0 || params.probedAvdName.length === 0) {
|
|
26
|
+
return "no-answer";
|
|
27
|
+
}
|
|
28
|
+
return params.probedAvdName === params.avdName ? "match" : "other-avd";
|
|
29
|
+
}
|
|
30
|
+
function resolveAvdProbeVerdict(results) {
|
|
31
|
+
const unreadableDeviceIds = [];
|
|
32
|
+
for (const result of results) {
|
|
33
|
+
switch (result.outcome) {
|
|
34
|
+
case "match": {
|
|
35
|
+
return { deviceId: result.deviceId, verdict: "reuse" };
|
|
36
|
+
}
|
|
37
|
+
case "no-answer": {
|
|
38
|
+
unreadableDeviceIds.push(result.deviceId);
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
case "not-an-emulator":
|
|
42
|
+
case "other-avd": {
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
default: {
|
|
46
|
+
return assertNever(result.outcome);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (unreadableDeviceIds.length > 0) {
|
|
51
|
+
return { unreadableDeviceIds, verdict: "refuse" };
|
|
52
|
+
}
|
|
53
|
+
return { verdict: "start-new" };
|
|
54
|
+
}
|
|
55
|
+
export {
|
|
56
|
+
buildAvdProbeSummary,
|
|
57
|
+
buildUnreadableDevicesMessage,
|
|
58
|
+
checkIsEmulatorDeviceId,
|
|
59
|
+
classifyAvdProbe,
|
|
60
|
+
resolveAvdProbeVerdict
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2F2ZC1wcm9iZS12ZXJkaWN0LnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBmaWxlXG4gKlxuICogUHVyZSBjbGFzc2lmaWNhdGlvbiBvZiB0aGUgQVZEIGFkb3B0aW9uIHByb2JlIFx1MjAxNCBkZWNpZGluZywgZnJvbSB3aGF0IGVhY2hcbiAqIGNvbm5lY3RlZCBkZXZpY2UgYW5zd2VyZWQsIHdoZXRoZXIgdGhpcyBydW4gbWF5IHJldXNlIG9uZSwgbXVzdCBzdGFydCBpdHNcbiAqIG93biBlbXVsYXRvciwgb3IgY2Fubm90IHNhZmVseSBkbyBlaXRoZXIuXG4gKlxuICogVGhlIHByb2JlIChgYWRiIC1zIDxkZXZpY2U+IGVtdSBhdmQgbmFtZWApIHVzZWQgdG8gZGlzY2FyZCBpdHMgZXJyb3IgYW5kXG4gKiByZXNvbHZlIGAnJ2AsIHNvIGEgY2FsbCB0aGF0ICoqbmV2ZXIgYW5zd2VyZWQqKiB3YXMgaW5kaXN0aW5ndWlzaGFibGUgZnJvbSBvbmVcbiAqIHRoYXQgYW5zd2VyZWQgKlwiYSBkaWZmZXJlbnQgQVZEXCIqLiBCb3RoIGZlbGwgdGhyb3VnaCB0byBcInN0YXJ0IGEgbmV3XG4gKiBlbXVsYXRvclwiLCB3aGljaCBjb2xsaWRlcyB3aXRoIHRoZSBlbXVsYXRvciBhbHJlYWR5IHNlcnZpbmcgdGhhdCBBVkQ6XG4gKlxuICogYGBgdGV4dFxuICogMTQ6Mjc6NTIuMTE0ICBDaGVja2luZyBleGlzdGluZyBkZXZpY2VzIGZvciBBVkQgXCJvYnNpZGlhbl90ZXN0XCIuLi4gKGNvbm5lY3RlZDogW2VtdWxhdG9yLTU1NTRdKVxuICogMTQ6Mjc6NTcuMTcwICBBVkQgXCJvYnNpZGlhbl90ZXN0XCIgbm90IGZvdW5kIG9uIGFueSBleGlzdGluZyBkZXZpY2UsIHN0YXJ0aW5nIGEgbmV3IGVtdWxhdG9yLi4uXG4gKiBgYGBcbiAqXG4gKiA1LjA1NnMgYXBhcnQgXHUyMDE0IGV4YWN0bHkgdGhlIHByb2JlJ3Mgb3duIHRpbWVvdXQuIFRoZSBsYXVuY2ggdGhhdCBmb2xsb3dlZCBoaXRcbiAqIGBGQVRBTCB8IFJ1bm5pbmcgbXVsdGlwbGUgZW11bGF0b3JzIHdpdGggdGhlIHNhbWUgQVZEIGlzIGFuIGV4cGVyaW1lbnRhbFxuICogZmVhdHVyZWAsIHdoaWNoIHRoZSBlbXVsYXRvciB3cml0ZXMgdG8gaXRzIG93biBzdGRvdXQuICoqQSBwcm9iZSB0aGF0IG5ldmVyXG4gKiBhbnN3ZXJlZCBpcyBub3QgZXZpZGVuY2UgdGhhdCB0aGUgYW5zd2VyIGlzIG5vKiogXHUyMDE0IHRoZSBzYW1lIGRpc3RpbmN0aW9uXG4gKiBgYWRiLWRldmljZS1saXN0LnRzYCBkcmF3cyBiZXR3ZWVuIGBvZmZsaW5lYCBhbmQgYWJzZW50LCBhbmQgdGhlIHNhbWUgb25lXG4gKiB0aGUgY29ubmVjdGl2aXR5IHByb2JlIGRyYXdzIGJldHdlZW4gYSBmYWlsZWQgZHVtcCBhbmQgYSBtaXNzaW5nIG5ldHdvcmsuXG4gKlxuICogV29yc2UsIHRoZSBwcm9iZSBpcyBhc2tlZCBpdHMgcXVlc3Rpb24gcHJlY2lzZWx5IHdoZW4gdGhlIGd1ZXN0IGlzIGxlYXN0IGFibGVcbiAqIHRvIGFuc3dlciBpdCBcdTIwMTQgYSB3ZWRnZWQgZW11bGF0b3IgdGltZXMgb3V0IGV2ZXJ5IGBhZGJgIGNhbGwgXHUyMDE0IHdoaWNoIGlzIHRoZVxuICogY29uZGl0aW9uIHVuZGVyIHdoaWNoIGEgY29sbGlkaW5nIGxhdW5jaCBkb2VzIHRoZSBtb3N0IGRhbWFnZS5cbiAqXG4gKiBLZXB0IHNlcGFyYXRlIGZyb20gdGhlIGludGVncmF0aW9uLW9ubHkgYHRyYW5zcG9ydC1mYWN0b3J5YCAoZXhjbHVkZWQgZnJvbVxuICogdW5pdCB0ZXN0cykgc28gdGhlIGNsYXNzaWZpY2F0aW9uIHN0YXlzIHVuaXQtdGVzdGFibGUgXHUyMDE0IHRoZSBmYWN0b3J5IGl0c2VsZlxuICogc2hlbGxzIG91dCB0byBgYWRiYC5cbiAqL1xuXG5pbXBvcnQgeyBhc3NlcnROZXZlciB9IGZyb20gJy4vdHlwZS1ndWFyZHMubWpzJztcblxuLyoqXG4gKiBXaGF0IG9uZSBkZXZpY2UgYW5zd2VyZWQgd2hlbiBhc2tlZCB3aGljaCBBVkQgaXQgaXMgc2VydmluZy5cbiAqXG4gKiBgbm90LWFuLWVtdWxhdG9yYCBhbmQgYG90aGVyLWF2ZGAgYXJlIGJvdGggbGVnaXRpbWF0ZSBza2lwczsgb25seVxuICogYG5vLWFuc3dlcmAgaXMgdGhlIHNpbGVuY2UgdGhhdCBtdXN0IG5ldmVyIGJlIHJlYWQgYXMgb25lLlxuICovXG5leHBvcnQgdHlwZSBBdmRQcm9iZU91dGNvbWUgPSAnbWF0Y2gnIHwgJ25vLWFuc3dlcicgfCAnbm90LWFuLWVtdWxhdG9yJyB8ICdvdGhlci1hdmQnO1xuXG4vKipcbiAqIFRoZSBydW4gY2Fubm90IHRlbGwgd2hldGhlciB0aGUgQVZEIGlzIGFscmVhZHkgcnVubmluZywgc28gaXQgbXVzdCBub3QgbGF1bmNoLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEF2ZFByb2JlUmVmdXNlVmVyZGljdCB7XG4gIC8qKlxuICBUaGUgZGV2aWNlcyB0aGF0IGNvdWxkIG5vdCBiZSByZWFkLCBhbmQgdGhlcmVmb3JlIGNhbm5vdCBiZSBydWxlZCBvdXQgYXMgdGhlIEFWRCdzIGhvbGRlci5cbiAgICovXG4gIHJlYWRvbmx5IHVucmVhZGFibGVEZXZpY2VJZHM6IHN0cmluZ1tdO1xuXG4gIC8qKlxuICBEaXNjcmltaW5hbnQuXG4gICAqL1xuICByZWFkb25seSB2ZXJkaWN0OiAncmVmdXNlJztcbn1cblxuLyoqXG4gKiBPbmUgZGV2aWNlJ3MgcHJvYmUgb3V0Y29tZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBdmRQcm9iZVJlc3VsdCB7XG4gIC8qKlxuICBUaGUgZGV2aWNlIFVESUQsIGUuZy4gYGVtdWxhdG9yLTU1NTRgLlxuICAgKi9cbiAgcmVhZG9ubHkgZGV2aWNlSWQ6IHN0cmluZztcblxuICAvKipcbiAgV2hhdCB0aGUgZGV2aWNlIGFuc3dlcmVkLlxuICAgKi9cbiAgcmVhZG9ubHkgb3V0Y29tZTogQXZkUHJvYmVPdXRjb21lO1xufVxuXG4vKipcbiAqIFRoZSBBVkQgaXMgYWxyZWFkeSBydW5uaW5nLCBvbiBhIGRldmljZSB0aGlzIHJ1biBtYXkgYWRvcHQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXZkUHJvYmVSZXVzZVZlcmRpY3Qge1xuICAvKipcbiAgVGhlIGRldmljZSBhbHJlYWR5IHNlcnZpbmcgdGhlIHJlcXVlc3RlZCBBVkQuXG4gICAqL1xuICByZWFkb25seSBkZXZpY2VJZDogc3RyaW5nO1xuXG4gIC8qKlxuICBEaXNjcmltaW5hbnQuXG4gICAqL1xuICByZWFkb25seSB2ZXJkaWN0OiAncmV1c2UnO1xufVxuXG4vKipcbiAqIEV2ZXJ5IGRldmljZSBhbnN3ZXJlZCwgbm9uZSBpcyBzZXJ2aW5nIHRoZSBBVkQsIHNvIGxhdW5jaGluZyBjYW5ub3QgY29sbGlkZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBdmRQcm9iZVN0YXJ0TmV3VmVyZGljdCB7XG4gIC8qKlxuICBEaXNjcmltaW5hbnQuXG4gICAqL1xuICByZWFkb25seSB2ZXJkaWN0OiAnc3RhcnQtbmV3Jztcbn1cblxuLyoqXG4gKiBXaGF0IHRoZSBydW4gbWF5IGRvLCBnaXZlbiBldmVyeSBkZXZpY2UncyBwcm9iZSBvdXRjb21lLlxuICovXG5leHBvcnQgdHlwZSBBdmRQcm9iZVZlcmRpY3QgPSBBdmRQcm9iZVJlZnVzZVZlcmRpY3QgfCBBdmRQcm9iZVJldXNlVmVyZGljdCB8IEF2ZFByb2JlU3RhcnROZXdWZXJkaWN0O1xuXG4vKipcbiAqIFBhcmFtZXRlcnMgZm9yIHtAbGluayBidWlsZFVucmVhZGFibGVEZXZpY2VzTWVzc2FnZX0uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQnVpbGRVbnJlYWRhYmxlRGV2aWNlc01lc3NhZ2VQYXJhbXMge1xuICAvKipcbiAgVGhlIEFWRCB0aGUgcnVuIHdhbnRlZC5cbiAgICovXG4gIHJlYWRvbmx5IGF2ZE5hbWU6IHN0cmluZztcblxuICAvKipcbiAgVGhlIGJ1ZGdldCBlYWNoIHByb2JlIGF0dGVtcHQgd2FzIGdpdmVuLCBpbiBtaWxsaXNlY29uZHMuXG4gICAqL1xuICByZWFkb25seSBwcm9iZVRpbWVvdXRJbk1pbGxpc2Vjb25kczogbnVtYmVyO1xuXG4gIC8qKlxuICBUaGUgZGV2aWNlcyB0aGF0IGRpZCBub3QgYW5zd2VyLlxuICAgKi9cbiAgcmVhZG9ubHkgdW5yZWFkYWJsZURldmljZUlkczogcmVhZG9ubHkgc3RyaW5nW107XG59XG5cbi8qKlxuICogUGFyYW1ldGVycyBmb3Ige0BsaW5rIGNsYXNzaWZ5QXZkUHJvYmV9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIENsYXNzaWZ5QXZkUHJvYmVQYXJhbXMge1xuICAvKipcbiAgVGhlIEFWRCB0aGUgcnVuIHdhbnRzLlxuICAgKi9cbiAgcmVhZG9ubHkgYXZkTmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICBUaGUgZGV2aWNlIHRoYXQgd2FzIHByb2JlZC5cbiAgICovXG4gIHJlYWRvbmx5IGRldmljZUlkOiBzdHJpbmc7XG5cbiAgLyoqXG4gIFRoZSBBVkQgbmFtZSB0aGUgZGV2aWNlIGFuc3dlcmVkLCBvciBgdW5kZWZpbmVkYCB3aGVuIGl0IGRpZCBub3QgYW5zd2VyIGF0IGFsbC5cbiAgICovXG4gIHJlYWRvbmx5IHByb2JlZEF2ZE5hbWU/OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogTWF0Y2hlcyB0aGUgZGV2aWNlIElEcyBhZGIgZ2l2ZXMgZW11bGF0b3JzIHN0YXJ0ZWQgdGhlIHdheSB0aGlzIGhhcm5lc3NcbiAqIHN0YXJ0cyB0aGVtOiBgZW11bGF0b3IgLWF2ZCA8bmFtZT5gLCB3aG9zZSBjb25zb2xlIGxhbmRzIG9uIGEgbG9jYWwgcG9ydC5cbiAqXG4gKiBPbmx5IHN1Y2ggYSBkZXZpY2UgY2FuIGNvbGxpZGUgd2l0aCB0aGlzIHJ1bidzIGxhdW5jaCwgc28gb25seSBzdWNoIGEgZGV2aWNlJ3NcbiAqIHNpbGVuY2UgaXMgd29ydGggcmVmdXNpbmcgb3Zlci4gQSBwaHlzaWNhbCBoYW5kc2V0IChhbiBhcmJpdHJhcnkgc2VyaWFsKSBvciBhXG4gKiBUQ1AtYXR0YWNoZWQgZGV2aWNlIGFuc3dlcnMgYGFkYiBcdTIwMjYgZW11IGF2ZCBuYW1lYCB3aXRoIGFuIGVycm9yIGhvd2V2ZXIgaGVhbHRoeVxuICogaXQgaXM7IHJlYWRpbmcgdGhhdCBhcyBcImRpZCBub3QgYW5zd2VyXCIgd291bGQgYmxvY2sgZXZlcnkgcnVuIG9uIGEgaG9zdCB3aXRoIGFcbiAqIHBob25lIHBsdWdnZWQgaW4sIHdoaWNoIGlzIGEgd29yc2UgZGVmZWN0IHRoYW4gdGhlIG9uZSB0aGlzIG1vZHVsZSBmaXhlcy5cbiAqL1xuY29uc3QgRU1VTEFUT1JfREVWSUNFX0lEX1BBVFRFUk4gPSAvXmVtdWxhdG9yLVxcZCskLztcblxuLyoqXG4gKiBCdWlsZHMgdGhlIHN1bW1hcnkgbGluZSBuYW1pbmcgd2hhdCBlYWNoIGRldmljZSBhbnN3ZXJlZC5cbiAqXG4gKiBUaGUgb2xkIGxvZyBwcmludGVkIG9ubHkgdGhlIGNvbmNsdXNpb24gKGBub3QgZm91bmQgb24gYW55IGV4aXN0aW5nIGRldmljZWApLFxuICogd2hpY2ggaXMgZXhhY3RseSB0aGUgbGluZSB0aGF0IHdhcyB3cm9uZzsgcHJpbnRpbmcgdGhlIGV2aWRlbmNlIG5leHQgdG8gaXQgaXNcbiAqIHdoYXQgbWFrZXMgYSBiYWQgY29uY2x1c2lvbiB2aXNpYmxlIHdpdGhvdXQgYSBzZWNvbmQgcnVuLlxuICpcbiAqIEBwYXJhbSByZXN1bHRzIC0gRXZlcnkgZGV2aWNlJ3MgcHJvYmUgb3V0Y29tZS5cbiAqIEByZXR1cm5zIFRoZSBzdW1tYXJ5LCBvciBgbm8gZGV2aWNlc2Agd2hlbiBub3RoaW5nIHdhcyBjb25uZWN0ZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWlsZEF2ZFByb2JlU3VtbWFyeShyZXN1bHRzOiByZWFkb25seSBBdmRQcm9iZVJlc3VsdFtdKTogc3RyaW5nIHtcbiAgaWYgKHJlc3VsdHMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuICdubyBkZXZpY2VzJztcbiAgfVxuXG4gIHJldHVybiByZXN1bHRzLm1hcCgocmVzdWx0KSA9PiBgJHtyZXN1bHQuZGV2aWNlSWR9PSR7cmVzdWx0Lm91dGNvbWV9YCkuam9pbignLCAnKTtcbn1cblxuLyoqXG4gKiBCdWlsZHMgdGhlIHJlZnVzYWwgbWVzc2FnZSBmb3IgZGV2aWNlcyB0aGF0IGNvdWxkIG5vdCBiZSByZWFkLlxuICpcbiAqIE5hbWVzIHRoZSBkZXZpY2UsIHRoZSBBVkQsIHRoZSBidWRnZXQsIHRoZSBjb25zZXF1ZW5jZSBhbmQgdGhlIHJlY292ZXJ5IFx1MjAxNCB0aGVcbiAqIHNoYXBlIGB0ZWFyZG93bi12ZXJkaWN0LnRzYCB1c2VzIGZvciBpdHMgb3duIHdhcm5pbmcsIGJlY2F1c2UgYSBtZXNzYWdlIHRoYXRcbiAqIHN0b3BzIGEgcnVuIGhhcyB0byBsZWF2ZSB0aGUgcmVhZGVyIGFibGUgdG8gdW5ibG9jayBpdC5cbiAqXG4gKiBAcGFyYW0gcGFyYW1zIC0gVGhlIEFWRCwgdGhlIHByb2JlIGJ1ZGdldCwgYW5kIHRoZSBkZXZpY2VzIHRoYXQgZGlkIG5vdCBhbnN3ZXIuXG4gKiBAcmV0dXJucyBUaGUgcmVmdXNhbCBtZXNzYWdlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRVbnJlYWRhYmxlRGV2aWNlc01lc3NhZ2UocGFyYW1zOiBCdWlsZFVucmVhZGFibGVEZXZpY2VzTWVzc2FnZVBhcmFtcyk6IHN0cmluZyB7XG4gIC8qXG4gICAqIFdoZW4gdGhlcmUgaXMgZXhhY3RseSBvbmUgZGV2aWNlIHRoZSBqb2luZWQgbGlzdCBJUyBpdHMgSUQsIHNvIHRoZSBzaW5ndWxhclxuICAgKiB3b3JkaW5nIG5lZWRzIG5vIGluZGV4IGFjY2VzcyBcdTIwMTQgYW5kIG5vIHVucmVhY2hhYmxlIGZhbGxiYWNrIGZvciBvbmUuXG4gICAqL1xuICBjb25zdCBkZXZpY2VMaXN0ID0gcGFyYW1zLnVucmVhZGFibGVEZXZpY2VJZHMuam9pbignLCAnKTtcbiAgY29uc3QgaXNTaW5nbGUgPSBwYXJhbXMudW5yZWFkYWJsZURldmljZUlkcy5sZW5ndGggPT09IDE7XG5cbiAgY29uc3Qgc3ViamVjdCA9IGlzU2luZ2xlID8gYGRldmljZSAke2RldmljZUxpc3R9YCA6IGBkZXZpY2VzICR7ZGV2aWNlTGlzdH1gO1xuICBjb25zdCBjb21tYW5kID0gaXNTaW5nbGUgPyBgYWRiIC1zICR7ZGV2aWNlTGlzdH0gZW11IGF2ZCBuYW1lYCA6ICdhZGIgLXMgPGRldmljZT4gZW11IGF2ZCBuYW1lJztcbiAgY29uc3QgaG9sZGVyID0gaXNTaW5nbGUgPyAnaXQgaXMnIDogJ29uZSBvZiB0aGVtIGlzJztcbiAgY29uc3QgcmVtZWR5ID0gaXNTaW5nbGUgPyAnS2lsbCB0aGUgdW5yZXNwb25zaXZlIGRldmljZScgOiAnS2lsbCB0aGUgdW5yZXNwb25zaXZlIGRldmljZXMnO1xuXG4gIHJldHVybiBgQVZEIFwiJHtwYXJhbXMuYXZkTmFtZX1cIjogJHtzdWJqZWN0fSBkaWQgbm90IGFuc3dlciBcXGAke2NvbW1hbmR9XFxgIHdpdGhpbiAke1N0cmluZyhwYXJhbXMucHJvYmVUaW1lb3V0SW5NaWxsaXNlY29uZHMpfW1zIChyZXRyaWVkIG9uY2UpLCBgXG4gICAgKyBgc28gdGhpcyBydW4gY2Fubm90IHRlbGwgd2hldGhlciAke2hvbGRlcn0gYWxyZWFkeSBzZXJ2aW5nIHRoYXQgQVZELiBTdGFydGluZyBhbiBlbXVsYXRvciBhbnl3YXkgd291bGQgY29sbGlkZSBgXG4gICAgKyAnKGBGQVRBTCB8IFJ1bm5pbmcgbXVsdGlwbGUgZW11bGF0b3JzIHdpdGggdGhlIHNhbWUgQVZEIGlzIGFuIGV4cGVyaW1lbnRhbCBmZWF0dXJlYCksIHdoaWNoIHRoZSBlbXVsYXRvciByZXBvcnRzIG9ubHkgdG8gaXRzIG93biBzdGRvdXQuICdcbiAgICArIGAke3JlbWVkeX0sIG9yIHJ1biBcXGBhZGIga2lsbC1zZXJ2ZXJcXGAsIHRoZW4gcmV0cnkuYDtcbn1cblxuLyoqXG4gKiBEZWNpZGVzIHdoZXRoZXIgYSBkZXZpY2UgY2FuIGhvbGQgYW4gQVZEIHRoaXMgcnVuIGNvdWxkIGNvbGxpZGUgd2l0aC5cbiAqXG4gKiBAcGFyYW0gZGV2aWNlSWQgLSBUaGUgZGV2aWNlIFVESUQgdG8ganVkZ2UuXG4gKiBAcmV0dXJucyBgdHJ1ZWAgZm9yIGEgbG9jYWxseSBzdGFydGVkIGVtdWxhdG9yLCB3aG9zZSBjb25zb2xlIHRoaXMgcnVuIGNhbiBhc2suXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjaGVja0lzRW11bGF0b3JEZXZpY2VJZChkZXZpY2VJZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiBFTVVMQVRPUl9ERVZJQ0VfSURfUEFUVEVSTi50ZXN0KGRldmljZUlkKTtcbn1cblxuLyoqXG4gKiBDbGFzc2lmaWVzIG9uZSBkZXZpY2UncyBwcm9iZS5cbiAqXG4gKiBAcGFyYW0gcGFyYW1zIC0gVGhlIEFWRCB3YW50ZWQsIHRoZSBkZXZpY2UgcHJvYmVkLCBhbmQgd2hhdCBpdCBhbnN3ZXJlZC5cbiAqIEByZXR1cm5zIFRoZSBvdXRjb21lLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2xhc3NpZnlBdmRQcm9iZShwYXJhbXM6IENsYXNzaWZ5QXZkUHJvYmVQYXJhbXMpOiBBdmRQcm9iZU91dGNvbWUge1xuICBpZiAoIWNoZWNrSXNFbXVsYXRvckRldmljZUlkKHBhcmFtcy5kZXZpY2VJZCkpIHtcbiAgICByZXR1cm4gJ25vdC1hbi1lbXVsYXRvcic7XG4gIH1cblxuICBpZiAocGFyYW1zLnByb2JlZEF2ZE5hbWUgPT09IHVuZGVmaW5lZCB8fCBwYXJhbXMucHJvYmVkQXZkTmFtZS5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gJ25vLWFuc3dlcic7XG4gIH1cblxuICByZXR1cm4gcGFyYW1zLnByb2JlZEF2ZE5hbWUgPT09IHBhcmFtcy5hdmROYW1lID8gJ21hdGNoJyA6ICdvdGhlci1hdmQnO1xufVxuXG4vKipcbiAqIERlY2lkZXMgd2hhdCB0aGUgcnVuIG1heSBkbywgZnJvbSBldmVyeSBkZXZpY2UncyBwcm9iZSBvdXRjb21lLlxuICpcbiAqICoqQSBtYXRjaCB3aW5zIG92ZXIgYW4gdW5yZWFkYWJsZSBzaWJsaW5nLioqIE9uY2UgdGhlIHJlcXVlc3RlZCBBVkQgaXMgZm91bmRcbiAqIGFuZCByZXVzYWJsZSwgYW4gdW5yZWxhdGVkIHdlZGdlZCBkZXZpY2UgaXMgc29tZWJvZHkgZWxzZSdzIHByb2JsZW0gYW5kIG11c3RcbiAqIG5vdCBibG9jayBhIHJ1biB0aGF0IGhhcyBldmVyeXRoaW5nIGl0IG5lZWRzIFx1MjAxNCB0aGUgc2FtZSByZXN0cmFpbnRcbiAqIGBlbXVsYXRvci1iYWNrZW5kLnRzYCBzaG93cyBpbiBuZXZlciBzd2VlcGluZyBhIGBxZW11KmAgaXQgZG9lcyBub3Qgb3duLiBPbmx5XG4gKiB3aGVuIG5vdGhpbmcgbWF0Y2hlZCBkb2VzIHNpbGVuY2UgYmVjb21lIGRlY2lzaXZlLCBiZWNhdXNlIG9ubHkgdGhlbiB3b3VsZCB0aGVcbiAqIHJ1biBnbyBvbiB0byBsYXVuY2guXG4gKlxuICogQHBhcmFtIHJlc3VsdHMgLSBFdmVyeSBkZXZpY2UncyBwcm9iZSBvdXRjb21lLlxuICogQHJldHVybnMgVGhlIHZlcmRpY3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlQXZkUHJvYmVWZXJkaWN0KHJlc3VsdHM6IHJlYWRvbmx5IEF2ZFByb2JlUmVzdWx0W10pOiBBdmRQcm9iZVZlcmRpY3Qge1xuICBjb25zdCB1bnJlYWRhYmxlRGV2aWNlSWRzOiBzdHJpbmdbXSA9IFtdO1xuXG4gIGZvciAoY29uc3QgcmVzdWx0IG9mIHJlc3VsdHMpIHtcbiAgICBzd2l0Y2ggKHJlc3VsdC5vdXRjb21lKSB7XG4gICAgICBjYXNlICdtYXRjaCc6IHtcbiAgICAgICAgcmV0dXJuIHsgZGV2aWNlSWQ6IHJlc3VsdC5kZXZpY2VJZCwgdmVyZGljdDogJ3JldXNlJyB9O1xuICAgICAgfVxuICAgICAgY2FzZSAnbm8tYW5zd2VyJzoge1xuICAgICAgICB1bnJlYWRhYmxlRGV2aWNlSWRzLnB1c2gocmVzdWx0LmRldmljZUlkKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlICdub3QtYW4tZW11bGF0b3InOlxuICAgICAgY2FzZSAnb3RoZXItYXZkJzoge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGRlZmF1bHQ6IHtcbiAgICAgICAgcmV0dXJuIGFzc2VydE5ldmVyKHJlc3VsdC5vdXRjb21lKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBpZiAodW5yZWFkYWJsZURldmljZUlkcy5sZW5ndGggPiAwKSB7XG4gICAgcmV0dXJuIHsgdW5yZWFkYWJsZURldmljZUlkcywgdmVyZGljdDogJ3JlZnVzZScgfTtcbiAgfVxuXG4gIHJldHVybiB7IHZlcmRpY3Q6ICdzdGFydC1uZXcnIH07XG59XG4iXSwKICAibWFwcGluZ3MiOiAiQUFpQ0EsU0FBUyxtQkFBbUI7QUF3SDVCLE1BQU0sNkJBQTZCO0FBWTVCLFNBQVMscUJBQXFCLFNBQTRDO0FBQy9FLE1BQUksUUFBUSxXQUFXLEdBQUc7QUFDeEIsV0FBTztBQUFBLEVBQ1Q7QUFFQSxTQUFPLFFBQVEsSUFBSSxDQUFDLFdBQVcsR0FBRyxPQUFPLFFBQVEsSUFBSSxPQUFPLE9BQU8sRUFBRSxFQUFFLEtBQUssSUFBSTtBQUNsRjtBQVlPLFNBQVMsOEJBQThCLFFBQXFEO0FBS2pHLFFBQU0sYUFBYSxPQUFPLG9CQUFvQixLQUFLLElBQUk7QUFDdkQsUUFBTSxXQUFXLE9BQU8sb0JBQW9CLFdBQVc7QUFFdkQsUUFBTSxVQUFVLFdBQVcsVUFBVSxVQUFVLEtBQUssV0FBVyxVQUFVO0FBQ3pFLFFBQU0sVUFBVSxXQUFXLFVBQVUsVUFBVSxrQkFBa0I7QUFDakUsUUFBTSxTQUFTLFdBQVcsVUFBVTtBQUNwQyxRQUFNLFNBQVMsV0FBVyxpQ0FBaUM7QUFFM0QsU0FBTyxRQUFRLE9BQU8sT0FBTyxNQUFNLE9BQU8scUJBQXFCLE9BQU8sYUFBYSxPQUFPLE9BQU8sMEJBQTBCLENBQUMsc0RBQ3JGLE1BQU0sa05BRXRDLE1BQU07QUFDZjtBQVFPLFNBQVMsd0JBQXdCLFVBQTJCO0FBQ2pFLFNBQU8sMkJBQTJCLEtBQUssUUFBUTtBQUNqRDtBQVFPLFNBQVMsaUJBQWlCLFFBQWlEO0FBQ2hGLE1BQUksQ0FBQyx3QkFBd0IsT0FBTyxRQUFRLEdBQUc7QUFDN0MsV0FBTztBQUFBLEVBQ1Q7QUFFQSxNQUFJLE9BQU8sa0JBQWtCLFVBQWEsT0FBTyxjQUFjLFdBQVcsR0FBRztBQUMzRSxXQUFPO0FBQUEsRUFDVDtBQUVBLFNBQU8sT0FBTyxrQkFBa0IsT0FBTyxVQUFVLFVBQVU7QUFDN0Q7QUFlTyxTQUFTLHVCQUF1QixTQUFxRDtBQUMxRixRQUFNLHNCQUFnQyxDQUFDO0FBRXZDLGFBQVcsVUFBVSxTQUFTO0FBQzVCLFlBQVEsT0FBTyxTQUFTO0FBQUEsTUFDdEIsS0FBSyxTQUFTO0FBQ1osZUFBTyxFQUFFLFVBQVUsT0FBTyxVQUFVLFNBQVMsUUFBUTtBQUFBLE1BQ3ZEO0FBQUEsTUFDQSxLQUFLLGFBQWE7QUFDaEIsNEJBQW9CLEtBQUssT0FBTyxRQUFRO0FBQ3hDO0FBQUEsTUFDRjtBQUFBLE1BQ0EsS0FBSztBQUFBLE1BQ0wsS0FBSyxhQUFhO0FBQ2hCO0FBQUEsTUFDRjtBQUFBLE1BQ0EsU0FBUztBQUNQLGVBQU8sWUFBWSxPQUFPLE9BQU87QUFBQSxNQUNuQztBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBRUEsTUFBSSxvQkFBb0IsU0FBUyxHQUFHO0FBQ2xDLFdBQU8sRUFBRSxxQkFBcUIsU0FBUyxTQUFTO0FBQUEsRUFDbEQ7QUFFQSxTQUFPLEVBQUUsU0FBUyxZQUFZO0FBQ2hDOyIsCiAgIm5hbWVzIjogW10KfQo=
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* nothing but its plugin id — the id → repo lookup and the asset URL shapes.
|
|
6
6
|
*
|
|
7
7
|
* A plugin's built files never live in git: `.obsidian/plugins/*` is gitignored in
|
|
8
|
-
*
|
|
8
|
+
* a plugin repo, so a demo vault's injected community plugins exist on
|
|
9
9
|
* exactly the machine that once opened that vault in Obsidian. To install them
|
|
10
10
|
* headlessly (see `demo-vault-bootstrap.ts`) two things must be derivable:
|
|
11
11
|
*
|