obsidian-integration-testing 11.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.
Files changed (234) hide show
  1. package/dist/lib/cjs/adb-device-list.cjs +54 -0
  2. package/dist/lib/cjs/adb-device-list.d.cts +72 -0
  3. package/dist/lib/cjs/android-sdk.cjs +52 -0
  4. package/dist/lib/cjs/android-sdk.d.cts +29 -0
  5. package/dist/lib/cjs/app-startup-progress.cjs +87 -0
  6. package/dist/lib/cjs/app-startup-progress.d.cts +128 -0
  7. package/dist/lib/cjs/appium-server-marker.cjs +112 -0
  8. package/dist/lib/cjs/appium-server-marker.d.cts +103 -0
  9. package/dist/lib/cjs/avd-probe-verdict.cjs +90 -0
  10. package/dist/lib/cjs/avd-probe-verdict.d.cts +175 -0
  11. package/dist/lib/cjs/cli.cjs +104 -19
  12. package/dist/lib/cjs/cli.d.cts +16 -8
  13. package/dist/lib/cjs/community-plugin-registry.cjs +52 -0
  14. package/dist/lib/cjs/community-plugin-registry.d.cts +116 -0
  15. package/dist/lib/cjs/config-directory-fallback-error.cjs +57 -0
  16. package/dist/lib/cjs/config-directory-fallback-error.d.cts +64 -0
  17. package/dist/lib/cjs/config-directory.cjs +46 -0
  18. package/dist/lib/cjs/config-directory.d.cts +45 -0
  19. package/dist/lib/cjs/connect-to-cdp.cjs +13 -7
  20. package/dist/lib/cjs/connect-to-cdp.d.cts +19 -0
  21. package/dist/lib/cjs/context-provider.cjs +12 -1
  22. package/dist/lib/cjs/context-provider.d.cts +26 -3
  23. package/dist/lib/cjs/demo-vault-bootstrap.cjs +148 -0
  24. package/dist/lib/cjs/demo-vault-bootstrap.d.cts +114 -0
  25. package/dist/lib/cjs/demo-vault-populate.cjs +38 -10
  26. package/dist/lib/cjs/demo-vault-populate.d.cts +70 -0
  27. package/dist/lib/cjs/device-readiness.cjs +38 -3
  28. package/dist/lib/cjs/device-readiness.d.cts +83 -9
  29. package/dist/lib/cjs/emulator-arguments.cjs +6 -2
  30. package/dist/lib/cjs/emulator-arguments.d.cts +26 -0
  31. package/dist/lib/cjs/emulator-backend.cjs +71 -0
  32. package/dist/lib/cjs/emulator-backend.d.cts +76 -0
  33. package/dist/lib/cjs/emulator-liveness.cjs +72 -0
  34. package/dist/lib/cjs/emulator-liveness.d.cts +158 -0
  35. package/dist/lib/cjs/emulator-snapshot.cjs +57 -0
  36. package/dist/lib/cjs/emulator-snapshot.d.cts +68 -0
  37. package/dist/lib/cjs/eval-in-obsidian.cjs +1 -1
  38. package/dist/lib/cjs/eval-in-obsidian.d.cts +42 -13
  39. package/dist/lib/cjs/global-setup-core.cjs +30 -30
  40. package/dist/lib/cjs/global-setup-core.d.cts +27 -2
  41. package/dist/lib/cjs/headless-vault-config.cjs +51 -0
  42. package/dist/lib/cjs/headless-vault-config.d.cts +67 -0
  43. package/dist/lib/cjs/index.cjs +24 -1
  44. package/dist/lib/cjs/index.d.cts +14 -5
  45. package/dist/lib/cjs/installer-asset.cjs +1 -1
  46. package/dist/lib/cjs/installer-asset.d.cts +1 -1
  47. package/dist/lib/cjs/integration-setup-failed-error.cjs +62 -0
  48. package/dist/lib/cjs/integration-setup-failed-error.d.cts +66 -0
  49. package/dist/lib/cjs/jest/global-setup.cjs +2 -2
  50. package/dist/lib/cjs/jest/global-setup.d.cts +5 -1
  51. package/dist/lib/cjs/kill-process-tree.cjs +18 -7
  52. package/dist/lib/cjs/kill-process-tree.d.cts +10 -2
  53. package/dist/lib/cjs/library.cjs +1 -1
  54. package/dist/lib/cjs/mobile-input.cjs +173 -0
  55. package/dist/lib/cjs/mobile-input.d.cts +156 -0
  56. package/dist/lib/cjs/namespace-bootstrap.cjs +92 -9
  57. package/dist/lib/cjs/obsidian-installer.cjs +1 -1
  58. package/dist/lib/cjs/obsidian-instance.cjs +52 -3
  59. package/dist/lib/cjs/obsidian-instance.d.cts +12 -0
  60. package/dist/lib/cjs/obsidian-metadata.cjs +123 -17
  61. package/dist/lib/cjs/obsidian-metadata.d.cts +17 -6
  62. package/dist/lib/cjs/obsidian-version-switch.cjs +3 -3
  63. package/dist/lib/cjs/open-obsidian-settings-tab.cjs +1 -1
  64. package/dist/lib/cjs/open-obsidian-settings-tab.d.cts +3 -2
  65. package/dist/lib/cjs/owned-instance-exit-marker.cjs +99 -0
  66. package/dist/lib/cjs/owned-instance-exit-marker.d.cts +106 -0
  67. package/dist/lib/cjs/owned-instance-exited-error.cjs +106 -0
  68. package/dist/lib/cjs/owned-instance-exited-error.d.cts +98 -0
  69. package/dist/lib/cjs/owned-vault-seed.cjs +9 -5
  70. package/dist/lib/cjs/owned-vault-seed.d.cts +24 -3
  71. package/dist/lib/cjs/parent-liveness.cjs +42 -5
  72. package/dist/lib/cjs/parent-liveness.d.cts +37 -5
  73. package/dist/lib/cjs/port-owner.cjs +61 -0
  74. package/dist/lib/cjs/port-owner.d.cts +47 -0
  75. package/dist/lib/cjs/process-capture.cjs +62 -0
  76. package/dist/lib/cjs/process-capture.d.cts +83 -0
  77. package/dist/lib/cjs/process-exit-message.cjs +14 -8
  78. package/dist/lib/cjs/process-exit-message.d.cts +37 -3
  79. package/dist/lib/cjs/process-liveness.cjs +51 -0
  80. package/dist/lib/cjs/process-liveness.d.cts +18 -0
  81. package/dist/lib/cjs/release-catalog.cjs +73 -0
  82. package/dist/lib/cjs/release-catalog.d.cts +125 -0
  83. package/dist/lib/cjs/run-version-matrix.cjs +1 -1
  84. package/dist/lib/cjs/run-version-matrix.d.cts +1 -1
  85. package/dist/lib/cjs/teardown-verdict.cjs +53 -0
  86. package/dist/lib/cjs/teardown-verdict.d.cts +69 -0
  87. package/dist/lib/cjs/temporary-vault.cjs +43 -8
  88. package/dist/lib/cjs/temporary-vault.d.cts +47 -5
  89. package/dist/lib/cjs/transport-appium.cjs +223 -17
  90. package/dist/lib/cjs/transport-appium.d.cts +104 -3
  91. package/dist/lib/cjs/transport-desktop-cdp.cjs +201 -6
  92. package/dist/lib/cjs/transport-desktop-cdp.d.cts +100 -0
  93. package/dist/lib/cjs/transport-factory.cjs +1165 -142
  94. package/dist/lib/cjs/transport-factory.d.cts +10 -1
  95. package/dist/lib/cjs/transport-options.cjs +11 -3
  96. package/dist/lib/cjs/transport-options.d.cts +131 -12
  97. package/dist/lib/cjs/transport.cjs +1 -1
  98. package/dist/lib/cjs/transport.d.cts +7 -1
  99. package/dist/lib/cjs/vault-plugin-install.cjs +40 -0
  100. package/dist/lib/cjs/vault-plugin-install.d.cts +64 -0
  101. package/dist/lib/cjs/vault-teardown-verdict.cjs +42 -0
  102. package/dist/lib/cjs/vault-teardown-verdict.d.cts +57 -0
  103. package/dist/lib/cjs/version-matrix.cjs +1 -1
  104. package/dist/lib/cjs/version-matrix.d.cts +2 -2
  105. package/dist/lib/cjs/vitest/global-setup.cjs +13 -7
  106. package/dist/lib/cjs/vitest/global-setup.d.cts +5 -1
  107. package/dist/lib/cjs/vitest/setup.cjs +2 -1
  108. package/dist/lib/cjs/vitest/setup.d.cts +5 -0
  109. package/dist/lib/cjs/vitest/typings.d.cts +6 -4
  110. package/dist/lib/cjs/webview-cdp.cjs +263 -0
  111. package/dist/lib/cjs/webview-cdp.d.cts +156 -0
  112. package/dist/lib/cjs/wedged-appium-server.cjs +113 -0
  113. package/dist/lib/cjs/wedged-appium-server.d.cts +187 -0
  114. package/dist/lib/esm/adb-device-list.d.mts +72 -0
  115. package/dist/lib/esm/adb-device-list.mjs +28 -0
  116. package/dist/lib/esm/android-sdk.d.mts +29 -0
  117. package/dist/lib/esm/android-sdk.mjs +18 -0
  118. package/dist/lib/esm/app-startup-progress.d.mts +128 -0
  119. package/dist/lib/esm/app-startup-progress.mjs +59 -0
  120. package/dist/lib/esm/appium-server-marker.d.mts +103 -0
  121. package/dist/lib/esm/appium-server-marker.mjs +89 -0
  122. package/dist/lib/esm/avd-probe-verdict.d.mts +175 -0
  123. package/dist/lib/esm/avd-probe-verdict.mjs +62 -0
  124. package/dist/lib/esm/cli.d.mts +16 -8
  125. package/dist/lib/esm/cli.mjs +110 -19
  126. package/dist/lib/esm/community-plugin-registry.d.mts +116 -0
  127. package/dist/lib/esm/community-plugin-registry.mjs +23 -0
  128. package/dist/lib/esm/config-directory-fallback-error.d.mts +64 -0
  129. package/dist/lib/esm/config-directory-fallback-error.mjs +33 -0
  130. package/dist/lib/esm/config-directory.d.mts +45 -0
  131. package/dist/lib/esm/config-directory.mjs +21 -0
  132. package/dist/lib/esm/connect-to-cdp.d.mts +19 -0
  133. package/dist/lib/esm/connect-to-cdp.mjs +13 -7
  134. package/dist/lib/esm/context-provider.d.mts +26 -3
  135. package/dist/lib/esm/context-provider.mjs +10 -1
  136. package/dist/lib/esm/demo-vault-bootstrap.d.mts +114 -0
  137. package/dist/lib/esm/demo-vault-bootstrap.mjs +127 -0
  138. package/dist/lib/esm/demo-vault-populate.d.mts +70 -0
  139. package/dist/lib/esm/demo-vault-populate.mjs +35 -9
  140. package/dist/lib/esm/device-readiness.d.mts +83 -9
  141. package/dist/lib/esm/device-readiness.mjs +34 -2
  142. package/dist/lib/esm/emulator-arguments.d.mts +26 -0
  143. package/dist/lib/esm/emulator-arguments.mjs +6 -2
  144. package/dist/lib/esm/emulator-backend.d.mts +76 -0
  145. package/dist/lib/esm/emulator-backend.mjs +45 -0
  146. package/dist/lib/esm/emulator-liveness.d.mts +158 -0
  147. package/dist/lib/esm/emulator-liveness.mjs +47 -0
  148. package/dist/lib/esm/emulator-snapshot.d.mts +68 -0
  149. package/dist/lib/esm/emulator-snapshot.mjs +32 -0
  150. package/dist/lib/esm/eval-in-obsidian.d.mts +42 -13
  151. package/dist/lib/esm/eval-in-obsidian.mjs +1 -1
  152. package/dist/lib/esm/global-setup-core.d.mts +27 -2
  153. package/dist/lib/esm/global-setup-core.mjs +34 -35
  154. package/dist/lib/esm/headless-vault-config.d.mts +67 -0
  155. package/dist/lib/esm/headless-vault-config.mjs +31 -0
  156. package/dist/lib/esm/index.d.mts +14 -5
  157. package/dist/lib/esm/index.mjs +26 -2
  158. package/dist/lib/esm/installer-asset.d.mts +1 -1
  159. package/dist/lib/esm/installer-asset.mjs +1 -1
  160. package/dist/lib/esm/integration-setup-failed-error.d.mts +66 -0
  161. package/dist/lib/esm/integration-setup-failed-error.mjs +38 -0
  162. package/dist/lib/esm/jest/global-setup.d.mts +5 -1
  163. package/dist/lib/esm/jest/global-setup.mjs +2 -2
  164. package/dist/lib/esm/kill-process-tree.d.mts +10 -2
  165. package/dist/lib/esm/kill-process-tree.mjs +16 -6
  166. package/dist/lib/esm/library.mjs +1 -1
  167. package/dist/lib/esm/mobile-input.d.mts +156 -0
  168. package/dist/lib/esm/mobile-input.mjs +144 -0
  169. package/dist/lib/esm/namespace-bootstrap.mjs +95 -9
  170. package/dist/lib/esm/obsidian-installer.mjs +1 -1
  171. package/dist/lib/esm/obsidian-instance.d.mts +12 -0
  172. package/dist/lib/esm/obsidian-instance.mjs +55 -3
  173. package/dist/lib/esm/obsidian-metadata.d.mts +17 -6
  174. package/dist/lib/esm/obsidian-metadata.mjs +123 -17
  175. package/dist/lib/esm/obsidian-version-switch.mjs +3 -3
  176. package/dist/lib/esm/open-obsidian-settings-tab.d.mts +3 -2
  177. package/dist/lib/esm/open-obsidian-settings-tab.mjs +1 -1
  178. package/dist/lib/esm/owned-instance-exit-marker.d.mts +106 -0
  179. package/dist/lib/esm/owned-instance-exit-marker.mjs +78 -0
  180. package/dist/lib/esm/owned-instance-exited-error.d.mts +98 -0
  181. package/dist/lib/esm/owned-instance-exited-error.mjs +81 -0
  182. package/dist/lib/esm/owned-vault-seed.d.mts +24 -3
  183. package/dist/lib/esm/owned-vault-seed.mjs +9 -5
  184. package/dist/lib/esm/parent-liveness.d.mts +37 -5
  185. package/dist/lib/esm/parent-liveness.mjs +42 -5
  186. package/dist/lib/esm/port-owner.d.mts +47 -0
  187. package/dist/lib/esm/port-owner.mjs +36 -0
  188. package/dist/lib/esm/process-capture.d.mts +83 -0
  189. package/dist/lib/esm/process-capture.mjs +38 -0
  190. package/dist/lib/esm/process-exit-message.d.mts +37 -3
  191. package/dist/lib/esm/process-exit-message.mjs +13 -8
  192. package/dist/lib/esm/process-liveness.d.mts +18 -0
  193. package/dist/lib/esm/process-liveness.mjs +17 -0
  194. package/dist/lib/esm/release-catalog.d.mts +125 -0
  195. package/dist/lib/esm/release-catalog.mjs +46 -0
  196. package/dist/lib/esm/run-version-matrix.d.mts +1 -1
  197. package/dist/lib/esm/run-version-matrix.mjs +1 -1
  198. package/dist/lib/esm/teardown-verdict.d.mts +69 -0
  199. package/dist/lib/esm/teardown-verdict.mjs +28 -0
  200. package/dist/lib/esm/temporary-vault.d.mts +47 -5
  201. package/dist/lib/esm/temporary-vault.mjs +43 -8
  202. package/dist/lib/esm/transport-appium.d.mts +104 -3
  203. package/dist/lib/esm/transport-appium.mjs +233 -17
  204. package/dist/lib/esm/transport-desktop-cdp.d.mts +100 -0
  205. package/dist/lib/esm/transport-desktop-cdp.mjs +208 -7
  206. package/dist/lib/esm/transport-factory.d.mts +10 -1
  207. package/dist/lib/esm/transport-factory.mjs +1220 -149
  208. package/dist/lib/esm/transport-options.d.mts +131 -12
  209. package/dist/lib/esm/transport-options.mjs +9 -2
  210. package/dist/lib/esm/transport.d.mts +7 -1
  211. package/dist/lib/esm/vault-plugin-install.d.mts +64 -0
  212. package/dist/lib/esm/vault-plugin-install.mjs +20 -0
  213. package/dist/lib/esm/vault-teardown-verdict.d.mts +57 -0
  214. package/dist/lib/esm/vault-teardown-verdict.mjs +18 -0
  215. package/dist/lib/esm/version-matrix.d.mts +2 -2
  216. package/dist/lib/esm/version-matrix.mjs +1 -1
  217. package/dist/lib/esm/vitest/global-setup.d.mts +5 -1
  218. package/dist/lib/esm/vitest/global-setup.mjs +14 -7
  219. package/dist/lib/esm/vitest/setup.d.mts +5 -0
  220. package/dist/lib/esm/vitest/setup.mjs +3 -1
  221. package/dist/lib/esm/vitest/typings.d.mts +6 -4
  222. package/dist/lib/esm/webview-cdp.d.mts +156 -0
  223. package/dist/lib/esm/webview-cdp.mjs +235 -0
  224. package/dist/lib/esm/wedged-appium-server.d.mts +187 -0
  225. package/dist/lib/esm/wedged-appium-server.mjs +86 -0
  226. package/package.json +25 -23
  227. package/dist/lib/cjs/native-dialog-monitor.cjs +0 -192
  228. package/dist/lib/cjs/native-dialog-monitor.d.cts +0 -66
  229. package/dist/lib/cjs/obsidian-namespace.cjs +0 -17
  230. package/dist/lib/cjs/obsidian-namespace.d.cts +0 -128
  231. package/dist/lib/esm/native-dialog-monitor.d.mts +0 -66
  232. package/dist/lib/esm/native-dialog-monitor.mjs +0 -158
  233. package/dist/lib/esm/obsidian-namespace.d.mts +0 -128
  234. package/dist/lib/esm/obsidian-namespace.mjs +0 -1
@@ -0,0 +1,89 @@
1
+ import {
2
+ mkdirSync,
3
+ readFileSync,
4
+ rmSync,
5
+ writeFileSync
6
+ } from "node:fs";
7
+ import { tmpdir } from "node:os";
8
+ import { join } from "node:path";
9
+ import { log } from "./log.mjs";
10
+ import { checkIsProcessAlive } from "./process-liveness.mjs";
11
+ const MARKER_DIR_NAME = "obsidian-integration-testing";
12
+ const MARKER_FILE_SUFFIX = ".appium-server.json";
13
+ function checkIsHarnessOwnedAppiumServer(marker) {
14
+ if (!marker) {
15
+ return false;
16
+ }
17
+ return checkIsProcessAlive(marker.pid);
18
+ }
19
+ function clearAppiumServerMarker(port) {
20
+ try {
21
+ rmSync(getMarkerFilePath(port), { force: true });
22
+ } catch (error) {
23
+ log(`[appium-server-marker] Could not remove the marker for port ${String(port)}: ${getErrorMessage(error)}`);
24
+ }
25
+ }
26
+ function readAppiumServerMarker(port) {
27
+ let parsed;
28
+ try {
29
+ parsed = JSON.parse(readFileSync(getMarkerFilePath(port), "utf-8"));
30
+ } catch {
31
+ return void 0;
32
+ }
33
+ return parseMarker(parsed, port);
34
+ }
35
+ function recordAppiumServerStopAttempt(port) {
36
+ const marker = readAppiumServerMarker(port);
37
+ if (!marker) {
38
+ return;
39
+ }
40
+ writeMarker({ ...marker, stopAttemptedAtInMilliseconds: Date.now() });
41
+ }
42
+ function writeAppiumServerMarker(params) {
43
+ writeMarker({
44
+ pid: params.pid,
45
+ port: params.port,
46
+ startedAtInMilliseconds: Date.now()
47
+ });
48
+ }
49
+ function getErrorMessage(error) {
50
+ return error instanceof Error ? error.message : String(error);
51
+ }
52
+ function getMarkerDirectory() {
53
+ return join(tmpdir(), MARKER_DIR_NAME);
54
+ }
55
+ function getMarkerFilePath(port) {
56
+ return join(getMarkerDirectory(), `${String(port)}${MARKER_FILE_SUFFIX}`);
57
+ }
58
+ function parseMarker(parsed, port) {
59
+ if (typeof parsed !== "object" || parsed === null) {
60
+ return void 0;
61
+ }
62
+ const record = parsed;
63
+ const { pid, port: markedPort, startedAtInMilliseconds, stopAttemptedAtInMilliseconds } = record;
64
+ if (typeof pid !== "number" || typeof startedAtInMilliseconds !== "number" || markedPort !== port) {
65
+ return void 0;
66
+ }
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
+ }
81
+ }
82
+ export {
83
+ checkIsHarnessOwnedAppiumServer,
84
+ clearAppiumServerMarker,
85
+ readAppiumServerMarker,
86
+ recordAppiumServerStopAttempt,
87
+ writeAppiumServerMarker
88
+ };
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=
@@ -1,16 +1,24 @@
1
1
  /**
2
2
  * @file
3
3
  *
4
- * Thin CLI over {@link connectToCdp}: launches (or attaches to) a CDP-enabled
5
- * Obsidian instance with the runtime helper namespace bootstrapped, prints the
6
- * chosen CDP port/URL, and stays alive until interrupted so an external tool
7
- * (raw CDP `ws`, DevTools, …) can attach.
4
+ * The package's CLI. Two commands:
5
+ *
6
+ * - The **default** (no subcommand) — a thin CLI over {@link connectToCdp}: launches
7
+ * (or attaches to) a CDP-enabled Obsidian instance with the runtime helper
8
+ * namespace bootstrapped, prints the chosen CDP port/URL, and stays alive until
9
+ * interrupted so an external tool (raw CDP `ws`, DevTools, …) can attach.
10
+ * - **`bootstrap-demo-vault`** — installs a demo vault's injected community plugins
11
+ * headlessly (see `demo-vault-bootstrap.ts`). This is the copy-pasteable remedy
12
+ * `buildDemoVaultPopulate`'s throw names, replacing the GUI-only "open
13
+ * `demo-vault/` in Obsidian once" step that a fresh clone or CI cannot perform.
14
+ *
15
+ * Anything that is not a recognized subcommand falls through to the default
16
+ * command, so `obsidian-integration-testing --vault …` keeps working unchanged.
8
17
  */
9
18
  /**
10
- * Parses CLI arguments, opens the connection, prints its endpoint, and blocks
11
- * until `SIGINT`/`SIGTERM` or the owned Obsidian window is closed, disposing the
12
- * connection on shutdown.
19
+ * Dispatches to the requested subcommand, falling through to the default CDP
20
+ * command for anything that is not one.
13
21
  *
14
- * @returns A {@link Promise} that resolves once the connection has been disposed.
22
+ * @returns A {@link Promise} that resolves once the chosen command has finished.
15
23
  */
16
24
  export declare function main(): Promise<void>;
@@ -1,7 +1,116 @@
1
+ import {
2
+ existsSync,
3
+ readdirSync
4
+ } from "node:fs";
5
+ import {
6
+ join,
7
+ resolve as resolvePath
8
+ } from "node:path";
1
9
  import process from "node:process";
2
10
  import { parseArgs } from "node:util";
3
11
  import { connectToCdp } from "./connect-to-cdp.mjs";
12
+ import { bootstrapDemoVaultPlugins } from "./demo-vault-bootstrap.mjs";
13
+ const BOOTSTRAP_DEMO_VAULT_COMMAND = "bootstrap-demo-vault";
14
+ const HELP_FLAGS = /* @__PURE__ */ new Set(["--help", "-h"]);
15
+ const SUBCOMMAND_ARGUMENTS_START_INDEX = 3;
16
+ const USAGE = `Usage:
17
+ obsidian-integration-testing [options]
18
+ Launch (or attach to) a CDP-enabled Obsidian instance and print its endpoint.
19
+ Options: --vault, --port, --host, --obsidian-version, --obsidian-installer-version,
20
+ --command-timeout, --no-remove-vault
21
+
22
+ obsidian-integration-testing ${BOOTSTRAP_DEMO_VAULT_COMMAND} [options]
23
+ Install a demo vault's injected community plugins from their published GitHub
24
+ releases, so integration tests run without opening Obsidian by hand.
25
+ Options: --demo-vault <path> demo vault directory (default: ./demo-vault)
26
+ --plugin <id> plugin id to install (repeatable; default: every
27
+ id already present under .obsidian/plugins/)
28
+ --repo <owner/name> override the registry lookup (single --plugin only)
29
+ --version <tag> pin a release tag (single --plugin only)
30
+ --force re-download plugins that are already installed
31
+ `;
4
32
  async function main() {
33
+ const [, , firstArgument] = process.argv;
34
+ if (firstArgument !== void 0 && HELP_FLAGS.has(firstArgument)) {
35
+ process.stdout.write(USAGE);
36
+ return;
37
+ }
38
+ if (firstArgument === BOOTSTRAP_DEMO_VAULT_COMMAND) {
39
+ await runBootstrapDemoVaultCommand(process.argv.slice(SUBCOMMAND_ARGUMENTS_START_INDEX));
40
+ return;
41
+ }
42
+ await runConnectCommand();
43
+ }
44
+ function buildOptions(values) {
45
+ return {
46
+ ...values["command-timeout"] !== void 0 && { commandTimeoutInMilliseconds: parseNumber("command-timeout", values["command-timeout"]) },
47
+ ...values.host !== void 0 && { host: values.host },
48
+ ...values["no-remove-vault"] === true && { shouldRemoveVaultOnDispose: false },
49
+ ...values["obsidian-installer-version"] !== void 0 && { obsidianInstallerVersion: values["obsidian-installer-version"] },
50
+ ...values["obsidian-version"] !== void 0 && { obsidianVersion: values["obsidian-version"] },
51
+ ...values.port !== void 0 && { port: parseNumber("port", values.port) },
52
+ ...values.vault !== void 0 && { vault: values.vault }
53
+ };
54
+ }
55
+ function discoverDemoVaultPluginIds(demoVaultPath) {
56
+ const pluginsDirectory = join(demoVaultPath, ".obsidian", "plugins");
57
+ if (!existsSync(pluginsDirectory)) {
58
+ return [];
59
+ }
60
+ return readdirSync(pluginsDirectory, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
61
+ }
62
+ function parseNumber(flag, raw) {
63
+ const value = Number(raw);
64
+ if (!Number.isFinite(value)) {
65
+ throw new TypeError(`--${flag} must be a number, got: ${raw}`);
66
+ }
67
+ return value;
68
+ }
69
+ async function runBootstrapDemoVaultCommand(commandArguments) {
70
+ const { values } = parseArgs({
71
+ // eslint-disable-next-line unicorn/name-replacements -- `args` is Node's own `parseArgs` option name.
72
+ args: commandArguments,
73
+ options: {
74
+ "demo-vault": { type: "string" },
75
+ "force": { type: "boolean" },
76
+ "plugin": { multiple: true, type: "string" },
77
+ "repo": { type: "string" },
78
+ "version": { type: "string" }
79
+ }
80
+ });
81
+ const demoVaultPath = resolvePath(values["demo-vault"] ?? join(process.cwd(), "demo-vault"));
82
+ const pluginIds = values.plugin ?? discoverDemoVaultPluginIds(demoVaultPath);
83
+ if (pluginIds.length === 0) {
84
+ throw new Error(
85
+ `No community plugins to install: ${demoVaultPath} has no .obsidian/plugins/ entries. Name them explicitly, e.g. --plugin fix-require-modules.`
86
+ );
87
+ }
88
+ if (pluginIds.length > 1 && (values.repo !== void 0 || values.version !== void 0)) {
89
+ throw new Error("--repo and --version apply to a single plugin; pass exactly one --plugin, or run the command once per plugin.");
90
+ }
91
+ const injectPlugins = pluginIds.map((pluginId) => ({
92
+ pluginId,
93
+ ...values.repo !== void 0 && { repo: values.repo },
94
+ ...values.version !== void 0 && { version: values.version }
95
+ }));
96
+ const result = await bootstrapDemoVaultPlugins({
97
+ demoVaultPath,
98
+ injectPlugins,
99
+ shouldForce: values.force === true
100
+ });
101
+ for (const info of result.installed) {
102
+ process.stdout.write(`Installed ${info.pluginId} from ${info.repo}@${info.version ?? "latest"}: ${info.assetNames.join(", ")}
103
+ `);
104
+ }
105
+ if (result.skippedPluginIds.length > 0) {
106
+ process.stdout.write(`Already installed (use --force to re-download): ${result.skippedPluginIds.join(", ")}
107
+ `);
108
+ }
109
+ if (result.installed.length === 0) {
110
+ process.stdout.write("Nothing to install.\n");
111
+ }
112
+ }
113
+ async function runConnectCommand() {
5
114
  const { values } = parseArgs({
6
115
  options: {
7
116
  "command-timeout": { type: "string" },
@@ -27,24 +136,6 @@ Press Ctrl+C to stop.
27
136
  process.stdout.write("\nShutting down\u2026\n");
28
137
  await connection.dispose();
29
138
  }
30
- function buildOptions(values) {
31
- return {
32
- ...values["command-timeout"] !== void 0 && { commandTimeoutInMilliseconds: parseNumber("command-timeout", values["command-timeout"]) },
33
- ...values.host !== void 0 && { host: values.host },
34
- ...values["no-remove-vault"] === true && { shouldRemoveVaultOnDispose: false },
35
- ...values["obsidian-installer-version"] !== void 0 && { obsidianInstallerVersion: values["obsidian-installer-version"] },
36
- ...values["obsidian-version"] !== void 0 && { obsidianVersion: values["obsidian-version"] },
37
- ...values.port !== void 0 && { port: parseNumber("port", values.port) },
38
- ...values.vault !== void 0 && { vault: values.vault }
39
- };
40
- }
41
- function parseNumber(flag, raw) {
42
- const value = Number(raw);
43
- if (!Number.isFinite(value)) {
44
- throw new TypeError(`--${flag} must be a number, got: ${raw}`);
45
- }
46
- return value;
47
- }
48
139
  function waitForShutdownOrInstanceClose(cdpUrl) {
49
140
  const POLL_INTERVAL_IN_MILLISECONDS = 1e3;
50
141
  return new Promise((resolve) => {
@@ -79,4 +170,4 @@ function waitForShutdownOrInstanceClose(cdpUrl) {
79
170
  export {
80
171
  main
81
172
  };
82
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2NsaS50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIFRoaW4gQ0xJIG92ZXIge0BsaW5rIGNvbm5lY3RUb0NkcH06IGxhdW5jaGVzIChvciBhdHRhY2hlcyB0bykgYSBDRFAtZW5hYmxlZFxuICogT2JzaWRpYW4gaW5zdGFuY2Ugd2l0aCB0aGUgcnVudGltZSBoZWxwZXIgbmFtZXNwYWNlIGJvb3RzdHJhcHBlZCwgcHJpbnRzIHRoZVxuICogY2hvc2VuIENEUCBwb3J0L1VSTCwgYW5kIHN0YXlzIGFsaXZlIHVudGlsIGludGVycnVwdGVkIHNvIGFuIGV4dGVybmFsIHRvb2xcbiAqIChyYXcgQ0RQIGB3c2AsIERldlRvb2xzLCBcdTIwMjYpIGNhbiBhdHRhY2guXG4gKi9cblxuLyogdjggaWdub3JlIHN0YXJ0IC0tIEludGVncmF0aW9uLXRpbWUgQ0xJIChsYXVuY2hlcyBPYnNpZGlhbiAvIENEUCkgY292ZXJlZCBtYW51YWxseSwgbm90IGJ5IHVuaXQgdGVzdHMuICovXG5cbmltcG9ydCBwcm9jZXNzIGZyb20gJ25vZGU6cHJvY2Vzcyc7XG5pbXBvcnQgeyBwYXJzZUFyZ3MgfSBmcm9tICdub2RlOnV0aWwnO1xuXG5pbXBvcnQgdHlwZSB7IENvbm5lY3RUb0NkcE9wdGlvbnMgfSBmcm9tICcuL2Nvbm5lY3QtdG8tY2RwLm1qcyc7XG5cbmltcG9ydCB7IGNvbm5lY3RUb0NkcCB9IGZyb20gJy4vY29ubmVjdC10by1jZHAubWpzJztcblxuLyoqXG4gKiBUaGUgc2hhcGUgb2YgdGhlIHBhcnNlZCBDTEkgZmxhZyB2YWx1ZXMuXG4gKi9cbmludGVyZmFjZSBQYXJzZWRDbGlWYWx1ZXMge1xuICAnY29tbWFuZC10aW1lb3V0Jz86IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgJ2hvc3QnPzogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAnbm8tcmVtb3ZlLXZhdWx0Jz86IGJvb2xlYW4gfCB1bmRlZmluZWQ7XG4gICdvYnNpZGlhbi1pbnN0YWxsZXItdmVyc2lvbic/OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICdvYnNpZGlhbi12ZXJzaW9uJz86IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgJ3BvcnQnPzogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAndmF1bHQnPzogc3RyaW5nIHwgdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIFBhcnNlcyBDTEkgYXJndW1lbnRzLCBvcGVucyB0aGUgY29ubmVjdGlvbiwgcHJpbnRzIGl0cyBlbmRwb2ludCwgYW5kIGJsb2Nrc1xuICogdW50aWwgYFNJR0lOVGAvYFNJR1RFUk1gIG9yIHRoZSBvd25lZCBPYnNpZGlhbiB3aW5kb3cgaXMgY2xvc2VkLCBkaXNwb3NpbmcgdGhlXG4gKiBjb25uZWN0aW9uIG9uIHNodXRkb3duLlxuICpcbiAqIEByZXR1cm5zIEEge0BsaW5rIFByb21pc2V9IHRoYXQgcmVzb2x2ZXMgb25jZSB0aGUgY29ubmVjdGlvbiBoYXMgYmVlbiBkaXNwb3NlZC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG1haW4oKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHsgdmFsdWVzIH0gPSBwYXJzZUFyZ3Moe1xuICAgIG9wdGlvbnM6IHtcbiAgICAgICdjb21tYW5kLXRpbWVvdXQnOiB7IHR5cGU6ICdzdHJpbmcnIH0sXG4gICAgICAnaG9zdCc6IHsgdHlwZTogJ3N0cmluZycgfSxcbiAgICAgICduby1yZW1vdmUtdmF1bHQnOiB7IHR5cGU6ICdib29sZWFuJyB9LFxuICAgICAgJ29ic2lkaWFuLWluc3RhbGxlci12ZXJzaW9uJzogeyB0eXBlOiAnc3RyaW5nJyB9LFxuICAgICAgJ29ic2lkaWFuLXZlcnNpb24nOiB7IHR5cGU6ICdzdHJpbmcnIH0sXG4gICAgICAncG9ydCc6IHsgdHlwZTogJ3N0cmluZycgfSxcbiAgICAgICd2YXVsdCc6IHsgdHlwZTogJ3N0cmluZycgfVxuICAgIH1cbiAgfSk7XG5cbiAgY29uc3QgY29ubmVjdGlvbiA9IGF3YWl0IGNvbm5lY3RUb0NkcChidWlsZE9wdGlvbnModmFsdWVzKSk7XG5cbiAgcHJvY2Vzcy5zdGRvdXQud3JpdGUoXG4gICAgJ09ic2lkaWFuIENEUCByZWFkeS5cXG4nXG4gICAgICArIGAgIHBvcnQ6ICAgJHtTdHJpbmcoY29ubmVjdGlvbi5wb3J0KX1cXG5gXG4gICAgICArIGAgIGNkcFVybDogJHtjb25uZWN0aW9uLmNkcFVybH1cXG5gXG4gICAgICArIGAgIHZhdWx0OiAgJHtjb25uZWN0aW9uLnZhdWx0LnBhdGh9XFxuYFxuICAgICAgKyAnUnVudGltZSBoZWxwZXJzIGJvb3RzdHJhcHBlZCBhcyB3aW5kb3cuX19vYnNpZGlhbkludGVncmF0aW9uVGVzdGluZy5cXG4nXG4gICAgICArICdQcmVzcyBDdHJsK0MgdG8gc3RvcC5cXG4nXG4gICk7XG5cbiAgYXdhaXQgd2FpdEZvclNodXRkb3duT3JJbnN0YW5jZUNsb3NlKGNvbm5lY3Rpb24uY2RwVXJsKTtcblxuICBwcm9jZXNzLnN0ZG91dC53cml0ZSgnXFxuU2h1dHRpbmcgZG93blx1MjAyNlxcbicpO1xuICBhd2FpdCBjb25uZWN0aW9uLmRpc3Bvc2UoKTtcbn1cblxuLyoqXG4gKiBCdWlsZHMge0BsaW5rIENvbm5lY3RUb0NkcE9wdGlvbnN9IGZyb20gcGFyc2VkIENMSSBmbGFnIHZhbHVlcy5cbiAqXG4gKiBAcGFyYW0gdmFsdWVzIC0gVGhlIHBhcnNlZCBgcGFyc2VBcmdzYCB2YWx1ZXMuXG4gKiBAcmV0dXJucyBUaGUgY29ubmVjdGlvbiBvcHRpb25zLlxuICovXG5mdW5jdGlvbiBidWlsZE9wdGlvbnModmFsdWVzOiBQYXJzZWRDbGlWYWx1ZXMpOiBDb25uZWN0VG9DZHBPcHRpb25zIHtcbiAgcmV0dXJuIHtcbiAgICAuLi4odmFsdWVzWydjb21tYW5kLXRpbWVvdXQnXSAhPT0gdW5kZWZpbmVkICYmIHsgY29tbWFuZFRpbWVvdXRJbk1pbGxpc2Vjb25kczogcGFyc2VOdW1iZXIoJ2NvbW1hbmQtdGltZW91dCcsIHZhbHVlc1snY29tbWFuZC10aW1lb3V0J10pIH0pLFxuICAgIC4uLih2YWx1ZXMuaG9zdCAhPT0gdW5kZWZpbmVkICYmIHsgaG9zdDogdmFsdWVzLmhvc3QgfSksXG4gICAgLi4uKHZhbHVlc1snbm8tcmVtb3ZlLXZhdWx0J10gPT09IHRydWUgJiYgeyBzaG91bGRSZW1vdmVWYXVsdE9uRGlzcG9zZTogZmFsc2UgfSksXG4gICAgLi4uKHZhbHVlc1snb2JzaWRpYW4taW5zdGFsbGVyLXZlcnNpb24nXSAhPT0gdW5kZWZpbmVkICYmIHsgb2JzaWRpYW5JbnN0YWxsZXJWZXJzaW9uOiB2YWx1ZXNbJ29ic2lkaWFuLWluc3RhbGxlci12ZXJzaW9uJ10gfSksXG4gICAgLi4uKHZhbHVlc1snb2JzaWRpYW4tdmVyc2lvbiddICE9PSB1bmRlZmluZWQgJiYgeyBvYnNpZGlhblZlcnNpb246IHZhbHVlc1snb2JzaWRpYW4tdmVyc2lvbiddIH0pLFxuICAgIC4uLih2YWx1ZXMucG9ydCAhPT0gdW5kZWZpbmVkICYmIHsgcG9ydDogcGFyc2VOdW1iZXIoJ3BvcnQnLCB2YWx1ZXMucG9ydCkgfSksXG4gICAgLi4uKHZhbHVlcy52YXVsdCAhPT0gdW5kZWZpbmVkICYmIHsgdmF1bHQ6IHZhbHVlcy52YXVsdCB9KVxuICB9O1xufVxuXG4vKipcbiAqIFBhcnNlcyBhIG51bWVyaWMgQ0xJIGZsYWcgdmFsdWUsIHRocm93aW5nIG9uIGEgbm9uLWZpbml0ZSByZXN1bHQuXG4gKlxuICogQHBhcmFtIGZsYWcgLSBUaGUgZmxhZyBuYW1lIChmb3IgdGhlIGVycm9yIG1lc3NhZ2UpLlxuICogQHBhcmFtIHJhdyAtIFRoZSByYXcgc3RyaW5nIHZhbHVlLlxuICogQHJldHVybnMgVGhlIHBhcnNlZCBudW1iZXIuXG4gKiBAdGhyb3dzIEVycm9yIGlmIGByYXdgIGlzIG5vdCBhIGZpbml0ZSBudW1iZXIuXG4gKi9cbmZ1bmN0aW9uIHBhcnNlTnVtYmVyKGZsYWc6IHN0cmluZywgcmF3OiBzdHJpbmcpOiBudW1iZXIge1xuICBjb25zdCB2YWx1ZSA9IE51bWJlcihyYXcpO1xuICBpZiAoIU51bWJlci5pc0Zpbml0ZSh2YWx1ZSkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGAtLSR7ZmxhZ30gbXVzdCBiZSBhIG51bWJlciwgZ290OiAke3Jhd31gKTtcbiAgfVxuICByZXR1cm4gdmFsdWU7XG59XG5cbi8qKlxuICogUmVzb2x2ZXMgb25jZSB0aGUgcHJvY2VzcyByZWNlaXZlcyBgU0lHSU5UYC9gU0lHVEVSTWAsIG9yIHRoZSBDRFAgZW5kcG9pbnRcbiAqIHN0b3BzIGFuc3dlcmluZyAodGhlIG93bmVkIE9ic2lkaWFuIHdpbmRvdyB3YXMgY2xvc2VkKS5cbiAqXG4gKiBAcGFyYW0gY2RwVXJsIC0gVGhlIGNvbm5lY3Rpb24ncyBDRFAgYmFzZSBVUkwgdG8gcG9sbC5cbiAqIEByZXR1cm5zIEEge0BsaW5rIFByb21pc2V9IHRoYXQgcmVzb2x2ZXMgb24gdGhlIGZpcnN0IHNodXRkb3duIHRyaWdnZXIuXG4gKi9cbmZ1bmN0aW9uIHdhaXRGb3JTaHV0ZG93bk9ySW5zdGFuY2VDbG9zZShjZHBVcmw6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBQT0xMX0lOVEVSVkFMX0lOX01JTExJU0VDT05EUyA9IDEwMDA7XG4gIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgIGNvbnN0IHZlcnNpb25VcmwgPSBgJHtjZHBVcmx9L2pzb24vdmVyc2lvbmA7XG4gICAgbGV0IGlzU2V0dGxlZCA9IGZhbHNlO1xuXG4gICAgY29uc3QgdGltZXIgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICBwcm9iZUFsaXZlKCkuY2F0Y2goKCkgPT4ge1xuICAgICAgICAvLyBJZ25vcmUgcG9sbCBlcnJvcnMuXG4gICAgICB9KTtcbiAgICB9LCBQT0xMX0lOVEVSVkFMX0lOX01JTExJU0VDT05EUyk7XG5cbiAgICBwcm9jZXNzLm9uY2UoJ1NJR0lOVCcsIHNldHRsZSk7XG4gICAgcHJvY2Vzcy5vbmNlKCdTSUdURVJNJywgc2V0dGxlKTtcblxuICAgIGFzeW5jIGZ1bmN0aW9uIHByb2JlQWxpdmUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKHZlcnNpb25VcmwpO1xuICAgICAgICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgICAgICAgc2V0dGxlKCk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBUaGUgQ0RQIHBvcnQgc3RvcHBlZCBhbnN3ZXJpbmc6IHRoZSBPYnNpZGlhbiB3aW5kb3cgd2FzIGNsb3NlZC5cbiAgICAgICAgc2V0dGxlKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2V0dGxlKCk6IHZvaWQge1xuICAgICAgaWYgKGlzU2V0dGxlZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpc1NldHRsZWQgPSB0cnVlO1xuICAgICAgY2xlYXJJbnRlcnZhbCh0aW1lcik7XG4gICAgICByZXNvbHZlKCk7XG4gICAgfVxuICB9KTtcbn1cblxuLyogdjggaWdub3JlIHN0b3AgKi9cbiJdLAogICJtYXBwaW5ncyI6ICJBQVdBLE9BQU8sYUFBYTtBQUNwQixTQUFTLGlCQUFpQjtBQUkxQixTQUFTLG9CQUFvQjtBQXNCN0IsZUFBc0IsT0FBc0I7QUFDMUMsUUFBTSxFQUFFLE9BQU8sSUFBSSxVQUFVO0FBQUEsSUFDM0IsU0FBUztBQUFBLE1BQ1AsbUJBQW1CLEVBQUUsTUFBTSxTQUFTO0FBQUEsTUFDcEMsUUFBUSxFQUFFLE1BQU0sU0FBUztBQUFBLE1BQ3pCLG1CQUFtQixFQUFFLE1BQU0sVUFBVTtBQUFBLE1BQ3JDLDhCQUE4QixFQUFFLE1BQU0sU0FBUztBQUFBLE1BQy9DLG9CQUFvQixFQUFFLE1BQU0sU0FBUztBQUFBLE1BQ3JDLFFBQVEsRUFBRSxNQUFNLFNBQVM7QUFBQSxNQUN6QixTQUFTLEVBQUUsTUFBTSxTQUFTO0FBQUEsSUFDNUI7QUFBQSxFQUNGLENBQUM7QUFFRCxRQUFNLGFBQWEsTUFBTSxhQUFhLGFBQWEsTUFBTSxDQUFDO0FBRTFELFVBQVEsT0FBTztBQUFBLElBQ2I7QUFBQSxZQUNpQixPQUFPLFdBQVcsSUFBSSxDQUFDO0FBQUEsWUFDdkIsV0FBVyxNQUFNO0FBQUEsWUFDakIsV0FBVyxNQUFNLElBQUk7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQUd4QztBQUVBLFFBQU0sK0JBQStCLFdBQVcsTUFBTTtBQUV0RCxVQUFRLE9BQU8sTUFBTSx5QkFBb0I7QUFDekMsUUFBTSxXQUFXLFFBQVE7QUFDM0I7QUFRQSxTQUFTLGFBQWEsUUFBOEM7QUFDbEUsU0FBTztBQUFBLElBQ0wsR0FBSSxPQUFPLGlCQUFpQixNQUFNLFVBQWEsRUFBRSw4QkFBOEIsWUFBWSxtQkFBbUIsT0FBTyxpQkFBaUIsQ0FBQyxFQUFFO0FBQUEsSUFDekksR0FBSSxPQUFPLFNBQVMsVUFBYSxFQUFFLE1BQU0sT0FBTyxLQUFLO0FBQUEsSUFDckQsR0FBSSxPQUFPLGlCQUFpQixNQUFNLFFBQVEsRUFBRSw0QkFBNEIsTUFBTTtBQUFBLElBQzlFLEdBQUksT0FBTyw0QkFBNEIsTUFBTSxVQUFhLEVBQUUsMEJBQTBCLE9BQU8sNEJBQTRCLEVBQUU7QUFBQSxJQUMzSCxHQUFJLE9BQU8sa0JBQWtCLE1BQU0sVUFBYSxFQUFFLGlCQUFpQixPQUFPLGtCQUFrQixFQUFFO0FBQUEsSUFDOUYsR0FBSSxPQUFPLFNBQVMsVUFBYSxFQUFFLE1BQU0sWUFBWSxRQUFRLE9BQU8sSUFBSSxFQUFFO0FBQUEsSUFDMUUsR0FBSSxPQUFPLFVBQVUsVUFBYSxFQUFFLE9BQU8sT0FBTyxNQUFNO0FBQUEsRUFDMUQ7QUFDRjtBQVVBLFNBQVMsWUFBWSxNQUFjLEtBQXFCO0FBQ3RELFFBQU0sUUFBUSxPQUFPLEdBQUc7QUFDeEIsTUFBSSxDQUFDLE9BQU8sU0FBUyxLQUFLLEdBQUc7QUFDM0IsVUFBTSxJQUFJLFVBQVUsS0FBSyxJQUFJLDJCQUEyQixHQUFHLEVBQUU7QUFBQSxFQUMvRDtBQUNBLFNBQU87QUFDVDtBQVNBLFNBQVMsK0JBQStCLFFBQStCO0FBQ3JFLFFBQU0sZ0NBQWdDO0FBQ3RDLFNBQU8sSUFBSSxRQUFjLENBQUMsWUFBWTtBQUNwQyxVQUFNLGFBQWEsR0FBRyxNQUFNO0FBQzVCLFFBQUksWUFBWTtBQUVoQixVQUFNLFFBQVEsWUFBWSxNQUFNO0FBQzlCLGlCQUFXLEVBQUUsTUFBTSxNQUFNO0FBQUEsTUFFekIsQ0FBQztBQUFBLElBQ0gsR0FBRyw2QkFBNkI7QUFFaEMsWUFBUSxLQUFLLFVBQVUsTUFBTTtBQUM3QixZQUFRLEtBQUssV0FBVyxNQUFNO0FBRTlCLG1CQUFlLGFBQTRCO0FBQ3pDLFVBQUk7QUFDRixjQUFNLFdBQVcsTUFBTSxNQUFNLFVBQVU7QUFDdkMsWUFBSSxDQUFDLFNBQVMsSUFBSTtBQUNoQixpQkFBTztBQUFBLFFBQ1Q7QUFBQSxNQUNGLFFBQVE7QUFFTixlQUFPO0FBQUEsTUFDVDtBQUFBLElBQ0Y7QUFFQSxhQUFTLFNBQWU7QUFDdEIsVUFBSSxXQUFXO0FBQ2I7QUFBQSxNQUNGO0FBQ0Esa0JBQVk7QUFDWixvQkFBYyxLQUFLO0FBQ25CLGNBQVE7QUFBQSxJQUNWO0FBQUEsRUFDRixDQUFDO0FBQ0g7IiwKICAibmFtZXMiOiBbXQp9Cg==
173
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2NsaS50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIFRoZSBwYWNrYWdlJ3MgQ0xJLiBUd28gY29tbWFuZHM6XG4gKlxuICogLSBUaGUgKipkZWZhdWx0KiogKG5vIHN1YmNvbW1hbmQpIFx1MjAxNCBhIHRoaW4gQ0xJIG92ZXIge0BsaW5rIGNvbm5lY3RUb0NkcH06IGxhdW5jaGVzXG4gKiAgIChvciBhdHRhY2hlcyB0bykgYSBDRFAtZW5hYmxlZCBPYnNpZGlhbiBpbnN0YW5jZSB3aXRoIHRoZSBydW50aW1lIGhlbHBlclxuICogICBuYW1lc3BhY2UgYm9vdHN0cmFwcGVkLCBwcmludHMgdGhlIGNob3NlbiBDRFAgcG9ydC9VUkwsIGFuZCBzdGF5cyBhbGl2ZSB1bnRpbFxuICogICBpbnRlcnJ1cHRlZCBzbyBhbiBleHRlcm5hbCB0b29sIChyYXcgQ0RQIGB3c2AsIERldlRvb2xzLCBcdTIwMjYpIGNhbiBhdHRhY2guXG4gKiAtICoqYGJvb3RzdHJhcC1kZW1vLXZhdWx0YCoqIFx1MjAxNCBpbnN0YWxscyBhIGRlbW8gdmF1bHQncyBpbmplY3RlZCBjb21tdW5pdHkgcGx1Z2luc1xuICogICBoZWFkbGVzc2x5IChzZWUgYGRlbW8tdmF1bHQtYm9vdHN0cmFwLnRzYCkuIFRoaXMgaXMgdGhlIGNvcHktcGFzdGVhYmxlIHJlbWVkeVxuICogICBgYnVpbGREZW1vVmF1bHRQb3B1bGF0ZWAncyB0aHJvdyBuYW1lcywgcmVwbGFjaW5nIHRoZSBHVUktb25seSBcIm9wZW5cbiAqICAgYGRlbW8tdmF1bHQvYCBpbiBPYnNpZGlhbiBvbmNlXCIgc3RlcCB0aGF0IGEgZnJlc2ggY2xvbmUgb3IgQ0kgY2Fubm90IHBlcmZvcm0uXG4gKlxuICogQW55dGhpbmcgdGhhdCBpcyBub3QgYSByZWNvZ25pemVkIHN1YmNvbW1hbmQgZmFsbHMgdGhyb3VnaCB0byB0aGUgZGVmYXVsdFxuICogY29tbWFuZCwgc28gYG9ic2lkaWFuLWludGVncmF0aW9uLXRlc3RpbmcgLS12YXVsdCBcdTIwMjZgIGtlZXBzIHdvcmtpbmcgdW5jaGFuZ2VkLlxuICovXG5cbi8qIHY4IGlnbm9yZSBzdGFydCAtLSBJbnRlZ3JhdGlvbi10aW1lIENMSSAobGF1bmNoZXMgT2JzaWRpYW4gLyBDRFAsIGRvd25sb2FkcyByZWxlYXNlcykgY292ZXJlZCBtYW51YWxseSwgbm90IGJ5IHVuaXQgdGVzdHMuICovXG5cbmltcG9ydCB7XG4gIGV4aXN0c1N5bmMsXG4gIHJlYWRkaXJTeW5jXG59IGZyb20gJ25vZGU6ZnMnO1xuaW1wb3J0IHtcbiAgam9pbixcbiAgcmVzb2x2ZSBhcyByZXNvbHZlUGF0aFxufSBmcm9tICdub2RlOnBhdGgnO1xuaW1wb3J0IHByb2Nlc3MgZnJvbSAnbm9kZTpwcm9jZXNzJztcbmltcG9ydCB7IHBhcnNlQXJncyB9IGZyb20gJ25vZGU6dXRpbCc7XG5cbmltcG9ydCB0eXBlIHsgQ29ubmVjdFRvQ2RwT3B0aW9ucyB9IGZyb20gJy4vY29ubmVjdC10by1jZHAubWpzJztcbmltcG9ydCB0eXBlIHsgSW5qZWN0UGx1Z2luUGFyYW1zIH0gZnJvbSAnLi9kZW1vLXZhdWx0LXBvcHVsYXRlLm1qcyc7XG5cbmltcG9ydCB7IGNvbm5lY3RUb0NkcCB9IGZyb20gJy4vY29ubmVjdC10by1jZHAubWpzJztcbmltcG9ydCB7IGJvb3RzdHJhcERlbW9WYXVsdFBsdWdpbnMgfSBmcm9tICcuL2RlbW8tdmF1bHQtYm9vdHN0cmFwLm1qcyc7XG5cbmNvbnN0IEJPT1RTVFJBUF9ERU1PX1ZBVUxUX0NPTU1BTkQgPSAnYm9vdHN0cmFwLWRlbW8tdmF1bHQnO1xuY29uc3QgSEVMUF9GTEFHUyA9IG5ldyBTZXQoWyctLWhlbHAnLCAnLWgnXSk7XG5cbi8qKlxuSW5kZXggb2YgYSBzdWJjb21tYW5kJ3MgZmlyc3QgYXJndW1lbnQgaW4gYHByb2Nlc3MuYXJndmAgKGBbbm9kZSwgc2NyaXB0LCBzdWJjb21tYW5kLCBcdTIwMjZdYCkuXG4gKi9cbmNvbnN0IFNVQkNPTU1BTkRfQVJHVU1FTlRTX1NUQVJUX0lOREVYID0gMztcblxuY29uc3QgVVNBR0UgPSBgVXNhZ2U6XG4gIG9ic2lkaWFuLWludGVncmF0aW9uLXRlc3RpbmcgW29wdGlvbnNdXG4gICAgICBMYXVuY2ggKG9yIGF0dGFjaCB0bykgYSBDRFAtZW5hYmxlZCBPYnNpZGlhbiBpbnN0YW5jZSBhbmQgcHJpbnQgaXRzIGVuZHBvaW50LlxuICAgICAgT3B0aW9uczogLS12YXVsdCwgLS1wb3J0LCAtLWhvc3QsIC0tb2JzaWRpYW4tdmVyc2lvbiwgLS1vYnNpZGlhbi1pbnN0YWxsZXItdmVyc2lvbixcbiAgICAgICAgICAgICAgIC0tY29tbWFuZC10aW1lb3V0LCAtLW5vLXJlbW92ZS12YXVsdFxuXG4gIG9ic2lkaWFuLWludGVncmF0aW9uLXRlc3RpbmcgJHtCT09UU1RSQVBfREVNT19WQVVMVF9DT01NQU5EfSBbb3B0aW9uc11cbiAgICAgIEluc3RhbGwgYSBkZW1vIHZhdWx0J3MgaW5qZWN0ZWQgY29tbXVuaXR5IHBsdWdpbnMgZnJvbSB0aGVpciBwdWJsaXNoZWQgR2l0SHViXG4gICAgICByZWxlYXNlcywgc28gaW50ZWdyYXRpb24gdGVzdHMgcnVuIHdpdGhvdXQgb3BlbmluZyBPYnNpZGlhbiBieSBoYW5kLlxuICAgICAgT3B0aW9uczogLS1kZW1vLXZhdWx0IDxwYXRoPiAgIGRlbW8gdmF1bHQgZGlyZWN0b3J5IChkZWZhdWx0OiAuL2RlbW8tdmF1bHQpXG4gICAgICAgICAgICAgICAtLXBsdWdpbiA8aWQ+ICAgICAgICAgcGx1Z2luIGlkIHRvIGluc3RhbGwgKHJlcGVhdGFibGU7IGRlZmF1bHQ6IGV2ZXJ5XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQgYWxyZWFkeSBwcmVzZW50IHVuZGVyIC5vYnNpZGlhbi9wbHVnaW5zLylcbiAgICAgICAgICAgICAgIC0tcmVwbyA8b3duZXIvbmFtZT4gICBvdmVycmlkZSB0aGUgcmVnaXN0cnkgbG9va3VwIChzaW5nbGUgLS1wbHVnaW4gb25seSlcbiAgICAgICAgICAgICAgIC0tdmVyc2lvbiA8dGFnPiAgICAgICBwaW4gYSByZWxlYXNlIHRhZyAoc2luZ2xlIC0tcGx1Z2luIG9ubHkpXG4gICAgICAgICAgICAgICAtLWZvcmNlICAgICAgICAgICAgICAgcmUtZG93bmxvYWQgcGx1Z2lucyB0aGF0IGFyZSBhbHJlYWR5IGluc3RhbGxlZFxuYDtcblxuLyoqXG4gKiBUaGUgc2hhcGUgb2YgdGhlIHBhcnNlZCBDTEkgZmxhZyB2YWx1ZXMuXG4gKi9cbmludGVyZmFjZSBQYXJzZWRDbGlWYWx1ZXMge1xuICAnY29tbWFuZC10aW1lb3V0Jz86IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgJ2hvc3QnPzogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAnbm8tcmVtb3ZlLXZhdWx0Jz86IGJvb2xlYW4gfCB1bmRlZmluZWQ7XG4gICdvYnNpZGlhbi1pbnN0YWxsZXItdmVyc2lvbic/OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICdvYnNpZGlhbi12ZXJzaW9uJz86IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgJ3BvcnQnPzogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAndmF1bHQnPzogc3RyaW5nIHwgdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIERpc3BhdGNoZXMgdG8gdGhlIHJlcXVlc3RlZCBzdWJjb21tYW5kLCBmYWxsaW5nIHRocm91Z2ggdG8gdGhlIGRlZmF1bHQgQ0RQXG4gKiBjb21tYW5kIGZvciBhbnl0aGluZyB0aGF0IGlzIG5vdCBvbmUuXG4gKlxuICogQHJldHVybnMgQSB7QGxpbmsgUHJvbWlzZX0gdGhhdCByZXNvbHZlcyBvbmNlIHRoZSBjaG9zZW4gY29tbWFuZCBoYXMgZmluaXNoZWQuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBtYWluKCk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBbLCAsIGZpcnN0QXJndW1lbnRdID0gcHJvY2Vzcy5hcmd2O1xuXG4gIGlmIChmaXJzdEFyZ3VtZW50ICE9PSB1bmRlZmluZWQgJiYgSEVMUF9GTEFHUy5oYXMoZmlyc3RBcmd1bWVudCkpIHtcbiAgICBwcm9jZXNzLnN0ZG91dC53cml0ZShVU0FHRSk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKGZpcnN0QXJndW1lbnQgPT09IEJPT1RTVFJBUF9ERU1PX1ZBVUxUX0NPTU1BTkQpIHtcbiAgICBhd2FpdCBydW5Cb290c3RyYXBEZW1vVmF1bHRDb21tYW5kKHByb2Nlc3MuYXJndi5zbGljZShTVUJDT01NQU5EX0FSR1VNRU5UU19TVEFSVF9JTkRFWCkpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGF3YWl0IHJ1bkNvbm5lY3RDb21tYW5kKCk7XG59XG5cbi8qKlxuICogQnVpbGRzIHtAbGluayBDb25uZWN0VG9DZHBPcHRpb25zfSBmcm9tIHBhcnNlZCBDTEkgZmxhZyB2YWx1ZXMuXG4gKlxuICogQHBhcmFtIHZhbHVlcyAtIFRoZSBwYXJzZWQgYHBhcnNlQXJnc2AgdmFsdWVzLlxuICogQHJldHVybnMgVGhlIGNvbm5lY3Rpb24gb3B0aW9ucy5cbiAqL1xuZnVuY3Rpb24gYnVpbGRPcHRpb25zKHZhbHVlczogUGFyc2VkQ2xpVmFsdWVzKTogQ29ubmVjdFRvQ2RwT3B0aW9ucyB7XG4gIHJldHVybiB7XG4gICAgLi4uKHZhbHVlc1snY29tbWFuZC10aW1lb3V0J10gIT09IHVuZGVmaW5lZCAmJiB7IGNvbW1hbmRUaW1lb3V0SW5NaWxsaXNlY29uZHM6IHBhcnNlTnVtYmVyKCdjb21tYW5kLXRpbWVvdXQnLCB2YWx1ZXNbJ2NvbW1hbmQtdGltZW91dCddKSB9KSxcbiAgICAuLi4odmFsdWVzLmhvc3QgIT09IHVuZGVmaW5lZCAmJiB7IGhvc3Q6IHZhbHVlcy5ob3N0IH0pLFxuICAgIC4uLih2YWx1ZXNbJ25vLXJlbW92ZS12YXVsdCddID09PSB0cnVlICYmIHsgc2hvdWxkUmVtb3ZlVmF1bHRPbkRpc3Bvc2U6IGZhbHNlIH0pLFxuICAgIC4uLih2YWx1ZXNbJ29ic2lkaWFuLWluc3RhbGxlci12ZXJzaW9uJ10gIT09IHVuZGVmaW5lZCAmJiB7IG9ic2lkaWFuSW5zdGFsbGVyVmVyc2lvbjogdmFsdWVzWydvYnNpZGlhbi1pbnN0YWxsZXItdmVyc2lvbiddIH0pLFxuICAgIC4uLih2YWx1ZXNbJ29ic2lkaWFuLXZlcnNpb24nXSAhPT0gdW5kZWZpbmVkICYmIHsgb2JzaWRpYW5WZXJzaW9uOiB2YWx1ZXNbJ29ic2lkaWFuLXZlcnNpb24nXSB9KSxcbiAgICAuLi4odmFsdWVzLnBvcnQgIT09IHVuZGVmaW5lZCAmJiB7IHBvcnQ6IHBhcnNlTnVtYmVyKCdwb3J0JywgdmFsdWVzLnBvcnQpIH0pLFxuICAgIC4uLih2YWx1ZXMudmF1bHQgIT09IHVuZGVmaW5lZCAmJiB7IHZhdWx0OiB2YWx1ZXMudmF1bHQgfSlcbiAgfTtcbn1cblxuLyoqXG4gKiBMaXN0cyB0aGUgcGx1Z2luIGlkcyBhbHJlYWR5IHByZXNlbnQgdW5kZXIgYSBkZW1vIHZhdWx0J3MgYC5vYnNpZGlhbi9wbHVnaW5zL2AsIHVzZWQgYXMgdGhlIGRlZmF1bHRcbiAqIGluc3RhbGwgc2V0IHdoZW4gYC0tcGx1Z2luYCBpcyBvbWl0dGVkLiBBIGZvbGRlciB0aGF0IGV4aXN0cyBidXQgbGFja3MgYG1haW4uanNgIGlzIGV4YWN0bHkgdGhlIHN0YXRlXG4gKiB0aGlzIGNvbW1hbmQgcmVwYWlycywgc28gcHJlc2VuY2UgXHUyMDE0IG5vdCBjb21wbGV0ZW5lc3MgXHUyMDE0IGlzIHRoZSBjcml0ZXJpb24uXG4gKlxuICogQHBhcmFtIGRlbW9WYXVsdFBhdGggLSBUaGUgZGVtbyB2YXVsdCByb290LlxuICogQHJldHVybnMgVGhlIHBsdWdpbiBpZHMsIG9yIGFuIGVtcHR5IGFycmF5IHdoZW4gdGhlIHZhdWx0IGhhcyBubyBwbHVnaW5zIGZvbGRlci5cbiAqL1xuZnVuY3Rpb24gZGlzY292ZXJEZW1vVmF1bHRQbHVnaW5JZHMoZGVtb1ZhdWx0UGF0aDogc3RyaW5nKTogc3RyaW5nW10ge1xuICBjb25zdCBwbHVnaW5zRGlyZWN0b3J5ID0gam9pbihkZW1vVmF1bHRQYXRoLCAnLm9ic2lkaWFuJywgJ3BsdWdpbnMnKTtcbiAgaWYgKCFleGlzdHNTeW5jKHBsdWdpbnNEaXJlY3RvcnkpKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIHJldHVybiByZWFkZGlyU3luYyhwbHVnaW5zRGlyZWN0b3J5LCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSkuZmlsdGVyKChlbnRyeSkgPT4gZW50cnkuaXNEaXJlY3RvcnkoKSkubWFwKChlbnRyeSkgPT4gZW50cnkubmFtZSk7XG59XG5cbi8qKlxuICogUGFyc2VzIGEgbnVtZXJpYyBDTEkgZmxhZyB2YWx1ZSwgdGhyb3dpbmcgb24gYSBub24tZmluaXRlIHJlc3VsdC5cbiAqXG4gKiBAcGFyYW0gZmxhZyAtIFRoZSBmbGFnIG5hbWUgKGZvciB0aGUgZXJyb3IgbWVzc2FnZSkuXG4gKiBAcGFyYW0gcmF3IC0gVGhlIHJhdyBzdHJpbmcgdmFsdWUuXG4gKiBAcmV0dXJucyBUaGUgcGFyc2VkIG51bWJlci5cbiAqIEB0aHJvd3MgRXJyb3IgaWYgYHJhd2AgaXMgbm90IGEgZmluaXRlIG51bWJlci5cbiAqL1xuZnVuY3Rpb24gcGFyc2VOdW1iZXIoZmxhZzogc3RyaW5nLCByYXc6IHN0cmluZyk6IG51bWJlciB7XG4gIGNvbnN0IHZhbHVlID0gTnVtYmVyKHJhdyk7XG4gIGlmICghTnVtYmVyLmlzRmluaXRlKHZhbHVlKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYC0tJHtmbGFnfSBtdXN0IGJlIGEgbnVtYmVyLCBnb3Q6ICR7cmF3fWApO1xuICB9XG4gIHJldHVybiB2YWx1ZTtcbn1cblxuLyoqXG4gKiBSdW5zIHRoZSBgYm9vdHN0cmFwLWRlbW8tdmF1bHRgIHN1YmNvbW1hbmQuXG4gKlxuICogQHBhcmFtIGNvbW1hbmRBcmd1bWVudHMgLSBUaGUgc3ViY29tbWFuZCdzIGFyZ3VtZW50cyAoZXZlcnl0aGluZyBhZnRlciB0aGUgc3ViY29tbWFuZCBuYW1lKS5cbiAqIEByZXR1cm5zIEEge0BsaW5rIFByb21pc2V9IHRoYXQgcmVzb2x2ZXMgb25jZSB0aGUgaW5zdGFsbCBoYXMgZmluaXNoZWQuXG4gKiBAdGhyb3dzIEVycm9yIGlmIG5vIHBsdWdpbiBpZHMgY2FuIGJlIGRldGVybWluZWQsIG9yIGAtLXJlcG9gIC8gYC0tdmVyc2lvbmAgYXJlIHVzZWQgd2l0aCBzZXZlcmFsIHBsdWdpbnMuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJ1bkJvb3RzdHJhcERlbW9WYXVsdENvbW1hbmQoY29tbWFuZEFyZ3VtZW50czogc3RyaW5nW10pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgeyB2YWx1ZXMgfSA9IHBhcnNlQXJncyh7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHVuaWNvcm4vbmFtZS1yZXBsYWNlbWVudHMgLS0gYGFyZ3NgIGlzIE5vZGUncyBvd24gYHBhcnNlQXJnc2Agb3B0aW9uIG5hbWUuXG4gICAgYXJnczogY29tbWFuZEFyZ3VtZW50cyxcbiAgICBvcHRpb25zOiB7XG4gICAgICAnZGVtby12YXVsdCc6IHsgdHlwZTogJ3N0cmluZycgfSxcbiAgICAgICdmb3JjZSc6IHsgdHlwZTogJ2Jvb2xlYW4nIH0sXG4gICAgICAncGx1Z2luJzogeyBtdWx0aXBsZTogdHJ1ZSwgdHlwZTogJ3N0cmluZycgfSxcbiAgICAgICdyZXBvJzogeyB0eXBlOiAnc3RyaW5nJyB9LFxuICAgICAgJ3ZlcnNpb24nOiB7IHR5cGU6ICdzdHJpbmcnIH1cbiAgICB9XG4gIH0pO1xuXG4gIGNvbnN0IGRlbW9WYXVsdFBhdGggPSByZXNvbHZlUGF0aCh2YWx1ZXNbJ2RlbW8tdmF1bHQnXSA/PyBqb2luKHByb2Nlc3MuY3dkKCksICdkZW1vLXZhdWx0JykpO1xuICBjb25zdCBwbHVnaW5JZHMgPSB2YWx1ZXMucGx1Z2luID8/IGRpc2NvdmVyRGVtb1ZhdWx0UGx1Z2luSWRzKGRlbW9WYXVsdFBhdGgpO1xuXG4gIGlmIChwbHVnaW5JZHMubGVuZ3RoID09PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYE5vIGNvbW11bml0eSBwbHVnaW5zIHRvIGluc3RhbGw6ICR7ZGVtb1ZhdWx0UGF0aH0gaGFzIG5vIC5vYnNpZGlhbi9wbHVnaW5zLyBlbnRyaWVzLiBgXG4gICAgICAgICsgJ05hbWUgdGhlbSBleHBsaWNpdGx5LCBlLmcuIC0tcGx1Z2luIGZpeC1yZXF1aXJlLW1vZHVsZXMuJ1xuICAgICk7XG4gIH1cblxuICBpZiAocGx1Z2luSWRzLmxlbmd0aCA+IDEgJiYgKHZhbHVlcy5yZXBvICE9PSB1bmRlZmluZWQgfHwgdmFsdWVzLnZlcnNpb24gIT09IHVuZGVmaW5lZCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJy0tcmVwbyBhbmQgLS12ZXJzaW9uIGFwcGx5IHRvIGEgc2luZ2xlIHBsdWdpbjsgcGFzcyBleGFjdGx5IG9uZSAtLXBsdWdpbiwgb3IgcnVuIHRoZSBjb21tYW5kIG9uY2UgcGVyIHBsdWdpbi4nKTtcbiAgfVxuXG4gIGNvbnN0IGluamVjdFBsdWdpbnM6IEluamVjdFBsdWdpblBhcmFtc1tdID0gcGx1Z2luSWRzLm1hcCgocGx1Z2luSWQpID0+ICh7XG4gICAgcGx1Z2luSWQsXG4gICAgLi4uKHZhbHVlcy5yZXBvICE9PSB1bmRlZmluZWQgJiYgeyByZXBvOiB2YWx1ZXMucmVwbyB9KSxcbiAgICAuLi4odmFsdWVzLnZlcnNpb24gIT09IHVuZGVmaW5lZCAmJiB7IHZlcnNpb246IHZhbHVlcy52ZXJzaW9uIH0pXG4gIH0pKTtcblxuICBjb25zdCByZXN1bHQgPSBhd2FpdCBib290c3RyYXBEZW1vVmF1bHRQbHVnaW5zKHtcbiAgICBkZW1vVmF1bHRQYXRoLFxuICAgIGluamVjdFBsdWdpbnMsXG4gICAgc2hvdWxkRm9yY2U6IHZhbHVlcy5mb3JjZSA9PT0gdHJ1ZVxuICB9KTtcblxuICBmb3IgKGNvbnN0IGluZm8gb2YgcmVzdWx0Lmluc3RhbGxlZCkge1xuICAgIHByb2Nlc3Muc3Rkb3V0LndyaXRlKGBJbnN0YWxsZWQgJHtpbmZvLnBsdWdpbklkfSBmcm9tICR7aW5mby5yZXBvfUAke2luZm8udmVyc2lvbiA/PyAnbGF0ZXN0J306ICR7aW5mby5hc3NldE5hbWVzLmpvaW4oJywgJyl9XFxuYCk7XG4gIH1cblxuICBpZiAocmVzdWx0LnNraXBwZWRQbHVnaW5JZHMubGVuZ3RoID4gMCkge1xuICAgIHByb2Nlc3Muc3Rkb3V0LndyaXRlKGBBbHJlYWR5IGluc3RhbGxlZCAodXNlIC0tZm9yY2UgdG8gcmUtZG93bmxvYWQpOiAke3Jlc3VsdC5za2lwcGVkUGx1Z2luSWRzLmpvaW4oJywgJyl9XFxuYCk7XG4gIH1cblxuICBpZiAocmVzdWx0Lmluc3RhbGxlZC5sZW5ndGggPT09IDApIHtcbiAgICBwcm9jZXNzLnN0ZG91dC53cml0ZSgnTm90aGluZyB0byBpbnN0YWxsLlxcbicpO1xuICB9XG59XG5cbi8qKlxuICogUnVucyB0aGUgZGVmYXVsdCBjb21tYW5kOiBwYXJzZXMgQ0xJIGFyZ3VtZW50cywgb3BlbnMgdGhlIGNvbm5lY3Rpb24sIHByaW50cyBpdHNcbiAqIGVuZHBvaW50LCBhbmQgYmxvY2tzIHVudGlsIGBTSUdJTlRgL2BTSUdURVJNYCBvciB0aGUgb3duZWQgT2JzaWRpYW4gd2luZG93IGlzXG4gKiBjbG9zZWQsIGRpc3Bvc2luZyB0aGUgY29ubmVjdGlvbiBvbiBzaHV0ZG93bi5cbiAqXG4gKiBAcmV0dXJucyBBIHtAbGluayBQcm9taXNlfSB0aGF0IHJlc29sdmVzIG9uY2UgdGhlIGNvbm5lY3Rpb24gaGFzIGJlZW4gZGlzcG9zZWQuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJ1bkNvbm5lY3RDb21tYW5kKCk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCB7IHZhbHVlcyB9ID0gcGFyc2VBcmdzKHtcbiAgICBvcHRpb25zOiB7XG4gICAgICAnY29tbWFuZC10aW1lb3V0JzogeyB0eXBlOiAnc3RyaW5nJyB9LFxuICAgICAgJ2hvc3QnOiB7IHR5cGU6ICdzdHJpbmcnIH0sXG4gICAgICAnbm8tcmVtb3ZlLXZhdWx0JzogeyB0eXBlOiAnYm9vbGVhbicgfSxcbiAgICAgICdvYnNpZGlhbi1pbnN0YWxsZXItdmVyc2lvbic6IHsgdHlwZTogJ3N0cmluZycgfSxcbiAgICAgICdvYnNpZGlhbi12ZXJzaW9uJzogeyB0eXBlOiAnc3RyaW5nJyB9LFxuICAgICAgJ3BvcnQnOiB7IHR5cGU6ICdzdHJpbmcnIH0sXG4gICAgICAndmF1bHQnOiB7IHR5cGU6ICdzdHJpbmcnIH1cbiAgICB9XG4gIH0pO1xuXG4gIGNvbnN0IGNvbm5lY3Rpb24gPSBhd2FpdCBjb25uZWN0VG9DZHAoYnVpbGRPcHRpb25zKHZhbHVlcykpO1xuXG4gIHByb2Nlc3Muc3Rkb3V0LndyaXRlKFxuICAgICdPYnNpZGlhbiBDRFAgcmVhZHkuXFxuJ1xuICAgICAgKyBgICBwb3J0OiAgICR7U3RyaW5nKGNvbm5lY3Rpb24ucG9ydCl9XFxuYFxuICAgICAgKyBgICBjZHBVcmw6ICR7Y29ubmVjdGlvbi5jZHBVcmx9XFxuYFxuICAgICAgKyBgICB2YXVsdDogICR7Y29ubmVjdGlvbi52YXVsdC5wYXRofVxcbmBcbiAgICAgICsgJ1J1bnRpbWUgaGVscGVycyBib290c3RyYXBwZWQgYXMgd2luZG93Ll9fb2JzaWRpYW5JbnRlZ3JhdGlvblRlc3RpbmcuXFxuJ1xuICAgICAgKyAnUHJlc3MgQ3RybCtDIHRvIHN0b3AuXFxuJ1xuICApO1xuXG4gIGF3YWl0IHdhaXRGb3JTaHV0ZG93bk9ySW5zdGFuY2VDbG9zZShjb25uZWN0aW9uLmNkcFVybCk7XG5cbiAgcHJvY2Vzcy5zdGRvdXQud3JpdGUoJ1xcblNodXR0aW5nIGRvd25cdTIwMjZcXG4nKTtcbiAgYXdhaXQgY29ubmVjdGlvbi5kaXNwb3NlKCk7XG59XG5cbi8qKlxuICogUmVzb2x2ZXMgb25jZSB0aGUgcHJvY2VzcyByZWNlaXZlcyBgU0lHSU5UYC9gU0lHVEVSTWAsIG9yIHRoZSBDRFAgZW5kcG9pbnRcbiAqIHN0b3BzIGFuc3dlcmluZyAodGhlIG93bmVkIE9ic2lkaWFuIHdpbmRvdyB3YXMgY2xvc2VkKS5cbiAqXG4gKiBAcGFyYW0gY2RwVXJsIC0gVGhlIGNvbm5lY3Rpb24ncyBDRFAgYmFzZSBVUkwgdG8gcG9sbC5cbiAqIEByZXR1cm5zIEEge0BsaW5rIFByb21pc2V9IHRoYXQgcmVzb2x2ZXMgb24gdGhlIGZpcnN0IHNodXRkb3duIHRyaWdnZXIuXG4gKi9cbmZ1bmN0aW9uIHdhaXRGb3JTaHV0ZG93bk9ySW5zdGFuY2VDbG9zZShjZHBVcmw6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBQT0xMX0lOVEVSVkFMX0lOX01JTExJU0VDT05EUyA9IDEwMDA7XG4gIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgIGNvbnN0IHZlcnNpb25VcmwgPSBgJHtjZHBVcmx9L2pzb24vdmVyc2lvbmA7XG4gICAgbGV0IGlzU2V0dGxlZCA9IGZhbHNlO1xuXG4gICAgY29uc3QgdGltZXIgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICBwcm9iZUFsaXZlKCkuY2F0Y2goKCkgPT4ge1xuICAgICAgICAvLyBJZ25vcmUgcG9sbCBlcnJvcnMuXG4gICAgICB9KTtcbiAgICB9LCBQT0xMX0lOVEVSVkFMX0lOX01JTExJU0VDT05EUyk7XG5cbiAgICBwcm9jZXNzLm9uY2UoJ1NJR0lOVCcsIHNldHRsZSk7XG4gICAgcHJvY2Vzcy5vbmNlKCdTSUdURVJNJywgc2V0dGxlKTtcblxuICAgIGFzeW5jIGZ1bmN0aW9uIHByb2JlQWxpdmUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKHZlcnNpb25VcmwpO1xuICAgICAgICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgICAgICAgc2V0dGxlKCk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBUaGUgQ0RQIHBvcnQgc3RvcHBlZCBhbnN3ZXJpbmc6IHRoZSBPYnNpZGlhbiB3aW5kb3cgd2FzIGNsb3NlZC5cbiAgICAgICAgc2V0dGxlKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2V0dGxlKCk6IHZvaWQge1xuICAgICAgaWYgKGlzU2V0dGxlZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpc1NldHRsZWQgPSB0cnVlO1xuICAgICAgY2xlYXJJbnRlcnZhbCh0aW1lcik7XG4gICAgICByZXNvbHZlKCk7XG4gICAgfVxuICB9KTtcbn1cblxuLyogdjggaWdub3JlIHN0b3AgKi9cbiJdLAogICJtYXBwaW5ncyI6ICJBQW9CQTtBQUFBLEVBQ0U7QUFBQSxFQUNBO0FBQUEsT0FDSztBQUNQO0FBQUEsRUFDRTtBQUFBLEVBQ0EsV0FBVztBQUFBLE9BQ047QUFDUCxPQUFPLGFBQWE7QUFDcEIsU0FBUyxpQkFBaUI7QUFLMUIsU0FBUyxvQkFBb0I7QUFDN0IsU0FBUyxpQ0FBaUM7QUFFMUMsTUFBTSwrQkFBK0I7QUFDckMsTUFBTSxhQUFhLG9CQUFJLElBQUksQ0FBQyxVQUFVLElBQUksQ0FBQztBQUszQyxNQUFNLG1DQUFtQztBQUV6QyxNQUFNLFFBQVE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsaUNBTW1CLDRCQUE0QjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQThCN0QsZUFBc0IsT0FBc0I7QUFDMUMsUUFBTSxDQUFDLEVBQUUsRUFBRSxhQUFhLElBQUksUUFBUTtBQUVwQyxNQUFJLGtCQUFrQixVQUFhLFdBQVcsSUFBSSxhQUFhLEdBQUc7QUFDaEUsWUFBUSxPQUFPLE1BQU0sS0FBSztBQUMxQjtBQUFBLEVBQ0Y7QUFFQSxNQUFJLGtCQUFrQiw4QkFBOEI7QUFDbEQsVUFBTSw2QkFBNkIsUUFBUSxLQUFLLE1BQU0sZ0NBQWdDLENBQUM7QUFDdkY7QUFBQSxFQUNGO0FBRUEsUUFBTSxrQkFBa0I7QUFDMUI7QUFRQSxTQUFTLGFBQWEsUUFBOEM7QUFDbEUsU0FBTztBQUFBLElBQ0wsR0FBSSxPQUFPLGlCQUFpQixNQUFNLFVBQWEsRUFBRSw4QkFBOEIsWUFBWSxtQkFBbUIs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