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
@@ -24,11 +24,37 @@
24
24
  * So we use the one cross-platform resource the kernel *does* reclaim
25
25
  * deterministically on process death: a socket. The harness listens on a
26
26
  * loopback port and the instance's renderer connects to it. However the harness
27
- * dies — cleanly, `SIGKILL`ed, or crashed — the kernel closes its end, the
28
- * renderer sees `close`, and the window destroys itself. No polling, no
29
- * heartbeat interval, no timeout to tune.
27
+ * dies — cleanly, `SIGKILL`ed, or crashed — the kernel closes its end and the
28
+ * renderer sees `close`. No polling, no heartbeat interval, no timeout to tune.
30
29
  *
31
- * Deliberately fail-open: the renderer only arms the destroy handler after the
30
+ * **A close is a question, not a verdict.** A socket closing is not the same
31
+ * event as a process dying, and treating them as identical destroyed healthy
32
+ * instances: measured on 2026-09-05, a renderer's idle liveness socket sent
33
+ * `FIN` on its own — 3 min 13 s into one run, 11 min 56 s into another — while
34
+ * the harness was still listening and went on working for another 14 minutes.
35
+ * Every test file scheduled after the death then failed in tens of milliseconds
36
+ * with `ECONNREFUSED` on the dead CDP port; the worst run reported 156 such
37
+ * failures across 21 files, not one of them a test result. Why an idle unref'd
38
+ * loopback socket in an Electron renderer does that is not established, and does
39
+ * not need to be: the lifetimes vary run to run, so no fixed timeout explains it.
40
+ *
41
+ * So the `close` handler **verifies before destroying**: it reconnects to the
42
+ * same loopback port. A harness that is alive is still listening, so the
43
+ * reconnect succeeds and the new socket becomes the liveness token; only when
44
+ * nothing answers after a few tries — what a dead harness actually looks like —
45
+ * is the window destroyed. The leak the watchdog exists to prevent is still
46
+ * prevented, and the measured recovery is 11 ms.
47
+ *
48
+ * A reconnect rather than a check on the harness's process id, because it proves
49
+ * the thing the watchdog actually depends on — the liveness server still serving
50
+ * — and it stays correct against a *busy* harness: the kernel completes a
51
+ * loopback handshake out of the listen backlog even while Node's event loop is
52
+ * blocked. Its one residual ambiguity is accepted: a reconnect proves *something*
53
+ * is listening on that ephemeral port, not that it is ours. The probe follows the
54
+ * close by milliseconds, so another process winning that exact port in between is
55
+ * not a risk worth a handshake protocol.
56
+ *
57
+ * Deliberately fail-open: the renderer only arms the destroy path after the
32
58
  * connection is actually established. A watchdog that cannot reach the harness
33
59
  * leaves the instance running rather than killing a window the developer is
34
60
  * working in.
@@ -39,7 +65,13 @@
39
65
  */
40
66
  export interface ParentLivenessServer {
41
67
  /**
42
- Stops listening and drops every accepted connection.
68
+ * Stops listening.
69
+ *
70
+ * Node keeps already-accepted connections alive across a `close()`, so this
71
+ * does not by itself signal the renderer — the kernel reclaiming the socket on
72
+ * process death is what does. What it does guarantee is that a watchdog probe
73
+ * arriving afterwards is refused, which is the answer a torn-down harness
74
+ * should give.
43
75
  */
44
76
  close(): void;
45
77
  /**
@@ -1,5 +1,7 @@
1
1
  import { createServer } from "node:net";
2
2
  const PARENT_LIVENESS_HOST = "127.0.0.1";
3
+ const RECONNECT_ATTEMPT_LIMIT = 3;
4
+ const RECONNECT_DELAY_IN_MILLISECONDS = 250;
3
5
  function buildParentLivenessWatchdogExpression(port) {
4
6
  return `(function() {
5
7
  var FLAG = '__obsidianIntegrationTestingParentLiveness';
@@ -14,20 +16,55 @@ function buildParentLivenessWatchdogExpression(port) {
14
16
  return 'unavailable';
15
17
  }
16
18
  }
17
- var socket = net.connect(${String(port)}, '${PARENT_LIVENESS_HOST}');
19
+ var PORT = ${String(port)};
20
+ var HOST = '${PARENT_LIVENESS_HOST}';
21
+ var RECONNECT_ATTEMPT_LIMIT = ${String(RECONNECT_ATTEMPT_LIMIT)};
22
+ var RECONNECT_DELAY_IN_MILLISECONDS = ${String(RECONNECT_DELAY_IN_MILLISECONDS)};
23
+ var socket = net.connect(PORT, HOST);
18
24
  window[FLAG] = socket;
19
25
  var isConnected = false;
20
26
  socket.on('connect', function() { isConnected = true; });
21
- socket.on('error', function() { /* Handled by the close listener below. */ });
27
+ socket.on('error', function() { /* The close handler below decides what an error meant. */ });
22
28
  socket.on('close', function() {
29
+ /* Fail open: a connection that never established is no evidence the harness died. */
23
30
  if (!isConnected) { return; }
31
+ reconnect(1);
32
+ });
33
+ return 'armed';
34
+
35
+ /* A close only asks the question. Reconnecting answers it. */
36
+ function reconnect(attempt) {
37
+ var didConnect = false;
38
+ var probe = net.connect(PORT, HOST);
39
+ probe.on('connect', function() {
40
+ /* Someone is still listening, so the harness is alive. This is the new token. */
41
+ didConnect = true;
42
+ window[FLAG] = probe;
43
+ probe.on('close', function() { reconnect(1); });
44
+ });
45
+ probe.on('error', function() {
46
+ /*
47
+ * This handler outlives the connect, so it doubles as the adopted socket's
48
+ * error handler. Once connected, an error says nothing about the harness \u2014
49
+ * the close that follows it re-runs the probe.
50
+ */
51
+ if (didConnect) { return; }
52
+ if (attempt < RECONNECT_ATTEMPT_LIMIT) {
53
+ setTimeout(function() { reconnect(attempt + 1); }, RECONNECT_DELAY_IN_MILLISECONDS);
54
+ return;
55
+ }
56
+ /* Nothing answered after several tries: the harness really is gone. */
57
+ destroyWindow();
58
+ });
59
+ }
60
+
61
+ function destroyWindow() {
24
62
  try {
25
63
  window.electronWindow.destroy();
26
64
  } catch (destroyError) {
27
65
  window.close();
28
66
  }
29
- });
30
- return 'armed';
67
+ }
31
68
  })()`;
32
69
  }
33
70
  async function startParentLivenessServer() {
@@ -64,4 +101,4 @@ export {
64
101
  buildParentLivenessWatchdogExpression,
65
102
  startParentLivenessServer
66
103
  };
67
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3BhcmVudC1saXZlbmVzcy50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIFRpZXMgYSBoYXJuZXNzLW93bmVkIE9ic2lkaWFuIGluc3RhbmNlJ3MgbGlmZXRpbWUgdG8gdGhlIGhhcm5lc3MgcHJvY2VzcyB0aGF0XG4gKiBsYXVuY2hlZCBpdCwgaW4gdGhlIG9uZSBkaXJlY3Rpb24gdGhlIG9wZXJhdGluZyBzeXN0ZW0gd2lsbCBub3QgZG8gZm9yIHVzLlxuICpcbiAqIFRoZSBvd25lZCBpbnN0YW5jZSBpcyBhbHJlYWR5IGEgY2hpbGQgb2YgdGhlIGhhcm5lc3MgcHJvY2VzcywgYnV0IHRoYXQgbGlua1xuICogY2FycmllcyBubyBsaWZldGltZSBndWFyYW50ZWUuIFdpbmRvd3MgbmV2ZXIgcHJvcGFnYXRlcyBhIHBhcmVudCdzIGRlYXRoIHRvXG4gKiBpdHMgY2hpbGRyZW4gXHUyMDE0IGFuIG9ycGhhbiBzaW1wbHkga2VlcHMgcnVubmluZyB3aXRoIGEgc3RhbGUgcGFyZW50IGlkIFx1MjAxNCBhbmQgb25cbiAqIFBPU0lYIGEgYFNJR0tJTExgIGFpbWVkIGF0IGEgc2luZ2xlIHBpZCBuZXZlciBjYXNjYWRlcyBlaXRoZXIuIFRoZSBpbnN0YW5jZSBpc1xuICogYWRkaXRpb25hbGx5IHNwYXduZWQgYGRldGFjaGVkYCwgc28gaXQgaXMgbm90IGV2ZW4gaW4gdGhlIGhhcm5lc3MncyBwcm9jZXNzXG4gKiBncm91cC4gVGVhcmRvd24gdGhlcmVmb3JlIHJlbGllcyBlbnRpcmVseSBvbiB0aGUgaGFybmVzcyBydW5uaW5nIGl0cyBvd25cbiAqIGNsZWFudXAgKGBraWxsUHJvY2Vzc1RyZWVgIGZyb20gYW4gYGV4aXRgL3NpZ25hbCBoYW5kbGVyKSwgd2hpY2ggaXMgZXhhY3RseVxuICogd2hhdCBhIGBTSUdLSUxMYCwgYSBUYXNrIE1hbmFnZXIga2lsbCwgb3IgYW4gSURFIHN0b3AgYnV0dG9uIGRlbmllcyBpdC4gRXZlcnlcbiAqIHN1Y2gga2lsbCBsZWFrcyBhIGhpZGRlbiBPYnNpZGlhbiBob2xkaW5nIGEgdXNlci1kYXRhIGRpciBhbmQgYSBDRFAgcG9ydCwgYW5kXG4gKiB0aGV5IGFjY3VtdWxhdGU6IHRoZSBuZXh0IHJ1biBwaWNrcyBhIGZyZXNoIHRlbXAgZGlyIGFuZCBhIGZyZWUgcG9ydCwgc29cbiAqIG5vdGhpbmcgY29sbGlkZXMgYW5kIG5vdGhpbmcgY29tcGxhaW5zLlxuICpcbiAqIFRoZSBndWFyYW50ZWVkIGZpeCBpcyBhbiBPUyBwcmltaXRpdmUgXHUyMDE0IGEgV2luZG93cyBKb2IgT2JqZWN0IHdpdGhcbiAqIGBKT0JfT0JKRUNUX0xJTUlUX0tJTExfT05fSk9CX0NMT1NFYCwgb3IgYHByY3RsKFBSX1NFVF9QREVBVEhTSUcpYCBvbiBMaW51eCBcdTIwMTRcbiAqIGJ1dCBuZWl0aGVyIGlzIHJlYWNoYWJsZSBmcm9tIE5vZGUgd2l0aG91dCBhIG5hdGl2ZSBhZGRvbiwgd2hpY2ggaXMgZmFyIHRvb1xuICogaGVhdnkgYSBkZXBlbmRlbmN5IGZvciB0aGlzIGhhcm5lc3MuXG4gKlxuICogU28gd2UgdXNlIHRoZSBvbmUgY3Jvc3MtcGxhdGZvcm0gcmVzb3VyY2UgdGhlIGtlcm5lbCAqZG9lcyogcmVjbGFpbVxuICogZGV0ZXJtaW5pc3RpY2FsbHkgb24gcHJvY2VzcyBkZWF0aDogYSBzb2NrZXQuIFRoZSBoYXJuZXNzIGxpc3RlbnMgb24gYVxuICogbG9vcGJhY2sgcG9ydCBhbmQgdGhlIGluc3RhbmNlJ3MgcmVuZGVyZXIgY29ubmVjdHMgdG8gaXQuIEhvd2V2ZXIgdGhlIGhhcm5lc3NcbiAqIGRpZXMgXHUyMDE0IGNsZWFubHksIGBTSUdLSUxMYGVkLCBvciBjcmFzaGVkIFx1MjAxNCB0aGUga2VybmVsIGNsb3NlcyBpdHMgZW5kLCB0aGVcbiAqIHJlbmRlcmVyIHNlZXMgYGNsb3NlYCwgYW5kIHRoZSB3aW5kb3cgZGVzdHJveXMgaXRzZWxmLiBObyBwb2xsaW5nLCBub1xuICogaGVhcnRiZWF0IGludGVydmFsLCBubyB0aW1lb3V0IHRvIHR1bmUuXG4gKlxuICogRGVsaWJlcmF0ZWx5IGZhaWwtb3BlbjogdGhlIHJlbmRlcmVyIG9ubHkgYXJtcyB0aGUgZGVzdHJveSBoYW5kbGVyIGFmdGVyIHRoZVxuICogY29ubmVjdGlvbiBpcyBhY3R1YWxseSBlc3RhYmxpc2hlZC4gQSB3YXRjaGRvZyB0aGF0IGNhbm5vdCByZWFjaCB0aGUgaGFybmVzc1xuICogbGVhdmVzIHRoZSBpbnN0YW5jZSBydW5uaW5nIHJhdGhlciB0aGFuIGtpbGxpbmcgYSB3aW5kb3cgdGhlIGRldmVsb3BlciBpc1xuICogd29ya2luZyBpbi5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7IFNlcnZlciB9IGZyb20gJ25vZGU6bmV0JztcblxuaW1wb3J0IHsgY3JlYXRlU2VydmVyIH0gZnJvbSAnbm9kZTpuZXQnO1xuXG4vKipcbiAqIEEgbGlzdGVuaW5nIGxvb3BiYWNrIHNlcnZlciB3aG9zZSBhY2NlcHRlZCBjb25uZWN0aW9ucyBhY3QgYXMgbGl2ZW5lc3MgdG9rZW5zXG4gKiBmb3IgdGhlIGhhcm5lc3MgcHJvY2Vzcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQYXJlbnRMaXZlbmVzc1NlcnZlciB7XG4gIC8qKlxuICBTdG9wcyBsaXN0ZW5pbmcgYW5kIGRyb3BzIGV2ZXJ5IGFjY2VwdGVkIGNvbm5lY3Rpb24uXG4gICAqL1xuICBjbG9zZSgpOiB2b2lkO1xuXG4gIC8qKlxuICBUaGUgbG9vcGJhY2sgcG9ydCB0aGUgcmVuZGVyZXIgd2F0Y2hkb2cgc2hvdWxkIGNvbm5lY3QgYmFjayB0by5cbiAgICovXG4gIHJlYWRvbmx5IHBvcnQ6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBMb29wYmFjayBob3N0IHRoZSBsaXZlbmVzcyBzZXJ2ZXIgYmluZHMgdG8uIE5ldmVyIGV4cG9zZWQgb2ZmLW1hY2hpbmUuXG4gKi9cbmV4cG9ydCBjb25zdCBQQVJFTlRfTElWRU5FU1NfSE9TVCA9ICcxMjcuMC4wLjEnO1xuXG4vKipcbiAqIEJ1aWxkcyB0aGUgZXhwcmVzc2lvbiBldmFsdWF0ZWQgaW4gdGhlIG93bmVkIGluc3RhbmNlJ3MgcmVuZGVyZXIgdG8gYXJtIHRoZVxuICogd2F0Y2hkb2cuXG4gKlxuICogV3JpdHRlbiBpbiBFUzUgc3R5bGUgKGB2YXJgLCBgZnVuY3Rpb25gKSB3aXRoIG5vIG9wdGlvbmFsIGNoYWluaW5nLCBtYXRjaGluZ1xuICoge0BsaW5rIERJU01JU1NfVFJVU1RfRElBTE9HX0VYUFJ9OiB0aGUgc2FtZSBleHByZXNzaW9uIGhhcyB0byBwYXJzZSBvbiB0aGVcbiAqIENocm9taXVtIDgwLWVyYSByZW5kZXJlcnMgb2YgdGhlIG9sZGVzdCBzdXBwb3J0ZWQgT2JzaWRpYW4gdmVyc2lvbnMgKEwyNikuXG4gKlxuICogQXJtaW5nIGlzIGlkZW1wb3RlbnQgXHUyMDE0IGEgc2Vjb25kIGV2YWx1YXRpb24gZmluZHMgdGhlIHN0b3JlZCBzb2NrZXQgYW5kXG4gKiByZXR1cm5zIHdpdGhvdXQgb3BlbmluZyBhbm90aGVyIGNvbm5lY3Rpb24sIHNvIGEgcmV0cmllZCByZWFkaW5lc3MgcGFzcyBkb2VzXG4gKiBub3QgcGlsZSB1cCBzb2NrZXRzLlxuICpcbiAqIEBwYXJhbSBwb3J0IC0gVGhlIGxvb3BiYWNrIHBvcnQgcmV0dXJuZWQgYnkge0BsaW5rIHN0YXJ0UGFyZW50TGl2ZW5lc3NTZXJ2ZXJ9LlxuICogQHJldHVybnMgVGhlIGV4cHJlc3Npb24gdG8gZXZhbHVhdGUsIHlpZWxkaW5nIGAnYXJtZWQnYCwgYCdhbHJlYWR5LWFybWVkJ2AsIG9yIGAndW5hdmFpbGFibGUnYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkUGFyZW50TGl2ZW5lc3NXYXRjaGRvZ0V4cHJlc3Npb24ocG9ydDogbnVtYmVyKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAoZnVuY3Rpb24oKSB7XG4gIHZhciBGTEFHID0gJ19fb2JzaWRpYW5JbnRlZ3JhdGlvblRlc3RpbmdQYXJlbnRMaXZlbmVzcyc7XG4gIGlmICh3aW5kb3dbRkxBR10pIHsgcmV0dXJuICdhbHJlYWR5LWFybWVkJzsgfVxuICB2YXIgbmV0O1xuICB0cnkge1xuICAgIG5ldCA9IHdpbmRvdy5yZXF1aXJlKCdub2RlOm5ldCcpO1xuICB9IGNhdGNoIChub2RlUHJlZml4RXJyb3IpIHtcbiAgICB0cnkge1xuICAgICAgbmV0ID0gd2luZG93LnJlcXVpcmUoJ25ldCcpO1xuICAgIH0gY2F0Y2ggKGJhcmVQcmVmaXhFcnJvcikge1xuICAgICAgcmV0dXJuICd1bmF2YWlsYWJsZSc7XG4gICAgfVxuICB9XG4gIHZhciBzb2NrZXQgPSBuZXQuY29ubmVjdCgke1N0cmluZyhwb3J0KX0sICcke1BBUkVOVF9MSVZFTkVTU19IT1NUfScpO1xuICB3aW5kb3dbRkxBR10gPSBzb2NrZXQ7XG4gIHZhciBpc0Nvbm5lY3RlZCA9IGZhbHNlO1xuICBzb2NrZXQub24oJ2Nvbm5lY3QnLCBmdW5jdGlvbigpIHsgaXNDb25uZWN0ZWQgPSB0cnVlOyB9KTtcbiAgc29ja2V0Lm9uKCdlcnJvcicsIGZ1bmN0aW9uKCkgeyAvKiBIYW5kbGVkIGJ5IHRoZSBjbG9zZSBsaXN0ZW5lciBiZWxvdy4gKi8gfSk7XG4gIHNvY2tldC5vbignY2xvc2UnLCBmdW5jdGlvbigpIHtcbiAgICBpZiAoIWlzQ29ubmVjdGVkKSB7IHJldHVybjsgfVxuICAgIHRyeSB7XG4gICAgICB3aW5kb3cuZWxlY3Ryb25XaW5kb3cuZGVzdHJveSgpO1xuICAgIH0gY2F0Y2ggKGRlc3Ryb3lFcnJvcikge1xuICAgICAgd2luZG93LmNsb3NlKCk7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuICdhcm1lZCc7XG59KSgpYDtcbn1cblxuLyoqXG4gKiBTdGFydHMgdGhlIGxvb3BiYWNrIGxpdmVuZXNzIHNlcnZlciB0aGUgb3duZWQgaW5zdGFuY2UncyByZW5kZXJlciBjb25uZWN0c1xuICogYmFjayB0by5cbiAqXG4gKiBUaGUgc2VydmVyIGFuZCBldmVyeSBhY2NlcHRlZCBzb2NrZXQgYXJlIGB1bnJlZmBlZCwgc28gaG9sZGluZyBhIHdhdGNoZG9nXG4gKiBjb25uZWN0aW9uIG9wZW4gbmV2ZXIga2VlcHMgdGhlIGhhcm5lc3MgcHJvY2VzcyBhbGl2ZSBvbiBpdHMgb3duIFx1MjAxNCB0aGVcbiAqIGNvbm5lY3Rpb24gaXMgYSB0b2tlbiB0aGUga2VybmVsIHJlY2xhaW1zLCBub3Qgd29yayB0byB3YWl0IG9uLlxuICpcbiAqIEByZXR1cm5zIEEge0BsaW5rIFByb21pc2V9IHJlc29sdmluZyB0byB0aGUgbGlzdGVuaW5nIHtAbGluayBQYXJlbnRMaXZlbmVzc1NlcnZlcn0uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzdGFydFBhcmVudExpdmVuZXNzU2VydmVyKCk6IFByb21pc2U8UGFyZW50TGl2ZW5lc3NTZXJ2ZXI+IHtcbiAgY29uc3Qgc2VydmVyID0gY3JlYXRlU2VydmVyKChzb2NrZXQpID0+IHtcbiAgICBzb2NrZXQudW5yZWYoKTtcbiAgICAvLyBUaGUgY29ubmVjdGlvbiBjYXJyaWVzIG5vIGRhdGEgXHUyMDE0IGl0IGV4aXN0cyBvbmx5IHNvIGl0cyBjbG9zZSBpcyBvYnNlcnZhYmxlLlxuICAgIHNvY2tldC5vbignZXJyb3InLCAoKSA9PiB7XG4gICAgICAvLyBBIHJlbmRlcmVyIHRvcm4gZG93biBtaWQtY29ubmVjdGlvbiByZXNldHMgcmF0aGVyIHRoYW4gY2xvc2VzOyBub3QgYW4gZXJyb3IgaGVyZS5cbiAgICB9KTtcbiAgfSk7XG4gIHNlcnZlci51bnJlZigpO1xuXG4gIGNvbnN0IHBvcnQgPSBhd2FpdCBsaXN0ZW5PbkZyZWVMb29wYmFja1BvcnQoc2VydmVyKTtcbiAgcmV0dXJuIHtcbiAgICBjbG9zZSgpOiB2b2lkIHtcbiAgICAgIHNlcnZlci5jbG9zZSgpO1xuICAgIH0sXG4gICAgcG9ydFxuICB9O1xufVxuXG4vKipcbiAqIEJpbmRzIHRoZSBzZXJ2ZXIgdG8gYW4gZXBoZW1lcmFsIGxvb3BiYWNrIHBvcnQgYW5kIHJlcG9ydHMgd2hpY2ggb25lIGl0IGdvdC5cbiAqXG4gKiBAcGFyYW0gc2VydmVyIC0gVGhlIHNlcnZlciB0byBiaW5kLlxuICogQHJldHVybnMgQSB7QGxpbmsgUHJvbWlzZX0gcmVzb2x2aW5nIHRvIHRoZSBhc3NpZ25lZCBwb3J0LlxuICogQHRocm93cyBJZiB0aGUgc2VydmVyIHJlcG9ydHMgYW4gZXJyb3IgYmVmb3JlIGxpc3RlbmluZywgb3IgYmluZHMgdG8gYSBwaXBlIHJhdGhlciB0aGFuIGEgcG9ydC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gbGlzdGVuT25GcmVlTG9vcGJhY2tQb3J0KHNlcnZlcjogU2VydmVyKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlPG51bWJlcj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHNlcnZlci5vbmNlKCdlcnJvcicsIHJlamVjdCk7XG4gICAgc2VydmVyLmxpc3RlbigwLCBQQVJFTlRfTElWRU5FU1NfSE9TVCwgKCkgPT4ge1xuICAgICAgY29uc3QgYWRkcmVzcyA9IHNlcnZlci5hZGRyZXNzKCk7XG4gICAgICBpZiAoYWRkcmVzcyA9PT0gbnVsbCB8fCB0eXBlb2YgYWRkcmVzcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgc2VydmVyLmNsb3NlKCk7XG4gICAgICAgIHJlamVjdChuZXcgRXJyb3IoJ0ZhaWxlZCB0byBkZXRlcm1pbmUgdGhlIHBhcmVudC1saXZlbmVzcyBwb3J0LicpKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgcmVzb2x2ZShhZGRyZXNzLnBvcnQpO1xuICAgIH0pO1xuICB9KTtcbn1cbiJdLAogICJtYXBwaW5ncyI6ICJBQXNDQSxTQUFTLG9CQUFvQjtBQXFCdEIsTUFBTSx1QkFBdUI7QUFpQjdCLFNBQVMsc0NBQXNDLE1BQXNCO0FBQzFFLFNBQU87QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSw2QkFhb0IsT0FBTyxJQUFJLENBQUMsTUFBTSxvQkFBb0I7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBZW5FO0FBWUEsZUFBc0IsNEJBQTJEO0FBQy9FLFFBQU0sU0FBUyxhQUFhLENBQUMsV0FBVztBQUN0QyxXQUFPLE1BQU07QUFFYixXQUFPLEdBQUcsU0FBUyxNQUFNO0FBQUEsSUFFekIsQ0FBQztBQUFBLEVBQ0gsQ0FBQztBQUNELFNBQU8sTUFBTTtBQUViLFFBQU0sT0FBTyxNQUFNLHlCQUF5QixNQUFNO0FBQ2xELFNBQU87QUFBQSxJQUNMLFFBQWM7QUFDWixhQUFPLE1BQU07QUFBQSxJQUNmO0FBQUEsSUFDQTtBQUFBLEVBQ0Y7QUFDRjtBQVNBLGVBQWUseUJBQXlCLFFBQWlDO0FBQ3ZFLFNBQU8sSUFBSSxRQUFnQixDQUFDLFNBQVMsV0FBVztBQUM5QyxXQUFPLEtBQUssU0FBUyxNQUFNO0FBQzNCLFdBQU8sT0FBTyxHQUFHLHNCQUFzQixNQUFNO0FBQzNDLFlBQU0sVUFBVSxPQUFPLFFBQVE7QUFDL0IsVUFBSSxZQUFZLFFBQVEsT0FBTyxZQUFZLFVBQVU7QUFDbkQsZUFBTyxNQUFNO0FBQ2IsZUFBTyxJQUFJLE1BQU0sK0NBQStDLENBQUM7QUFDakU7QUFBQSxNQUNGO0FBQ0EsY0FBUSxRQUFRLElBQUk7QUFBQSxJQUN0QixDQUFDO0FBQUEsRUFDSCxDQUFDO0FBQ0g7IiwKICAibmFtZXMiOiBbXQp9Cg==
104
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3BhcmVudC1saXZlbmVzcy50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIFRpZXMgYSBoYXJuZXNzLW93bmVkIE9ic2lkaWFuIGluc3RhbmNlJ3MgbGlmZXRpbWUgdG8gdGhlIGhhcm5lc3MgcHJvY2VzcyB0aGF0XG4gKiBsYXVuY2hlZCBpdCwgaW4gdGhlIG9uZSBkaXJlY3Rpb24gdGhlIG9wZXJhdGluZyBzeXN0ZW0gd2lsbCBub3QgZG8gZm9yIHVzLlxuICpcbiAqIFRoZSBvd25lZCBpbnN0YW5jZSBpcyBhbHJlYWR5IGEgY2hpbGQgb2YgdGhlIGhhcm5lc3MgcHJvY2VzcywgYnV0IHRoYXQgbGlua1xuICogY2FycmllcyBubyBsaWZldGltZSBndWFyYW50ZWUuIFdpbmRvd3MgbmV2ZXIgcHJvcGFnYXRlcyBhIHBhcmVudCdzIGRlYXRoIHRvXG4gKiBpdHMgY2hpbGRyZW4gXHUyMDE0IGFuIG9ycGhhbiBzaW1wbHkga2VlcHMgcnVubmluZyB3aXRoIGEgc3RhbGUgcGFyZW50IGlkIFx1MjAxNCBhbmQgb25cbiAqIFBPU0lYIGEgYFNJR0tJTExgIGFpbWVkIGF0IGEgc2luZ2xlIHBpZCBuZXZlciBjYXNjYWRlcyBlaXRoZXIuIFRoZSBpbnN0YW5jZSBpc1xuICogYWRkaXRpb25hbGx5IHNwYXduZWQgYGRldGFjaGVkYCwgc28gaXQgaXMgbm90IGV2ZW4gaW4gdGhlIGhhcm5lc3MncyBwcm9jZXNzXG4gKiBncm91cC4gVGVhcmRvd24gdGhlcmVmb3JlIHJlbGllcyBlbnRpcmVseSBvbiB0aGUgaGFybmVzcyBydW5uaW5nIGl0cyBvd25cbiAqIGNsZWFudXAgKGBraWxsUHJvY2Vzc1RyZWVgIGZyb20gYW4gYGV4aXRgL3NpZ25hbCBoYW5kbGVyKSwgd2hpY2ggaXMgZXhhY3RseVxuICogd2hhdCBhIGBTSUdLSUxMYCwgYSBUYXNrIE1hbmFnZXIga2lsbCwgb3IgYW4gSURFIHN0b3AgYnV0dG9uIGRlbmllcyBpdC4gRXZlcnlcbiAqIHN1Y2gga2lsbCBsZWFrcyBhIGhpZGRlbiBPYnNpZGlhbiBob2xkaW5nIGEgdXNlci1kYXRhIGRpciBhbmQgYSBDRFAgcG9ydCwgYW5kXG4gKiB0aGV5IGFjY3VtdWxhdGU6IHRoZSBuZXh0IHJ1biBwaWNrcyBhIGZyZXNoIHRlbXAgZGlyIGFuZCBhIGZyZWUgcG9ydCwgc29cbiAqIG5vdGhpbmcgY29sbGlkZXMgYW5kIG5vdGhpbmcgY29tcGxhaW5zLlxuICpcbiAqIFRoZSBndWFyYW50ZWVkIGZpeCBpcyBhbiBPUyBwcmltaXRpdmUgXHUyMDE0IGEgV2luZG93cyBKb2IgT2JqZWN0IHdpdGhcbiAqIGBKT0JfT0JKRUNUX0xJTUlUX0tJTExfT05fSk9CX0NMT1NFYCwgb3IgYHByY3RsKFBSX1NFVF9QREVBVEhTSUcpYCBvbiBMaW51eCBcdTIwMTRcbiAqIGJ1dCBuZWl0aGVyIGlzIHJlYWNoYWJsZSBmcm9tIE5vZGUgd2l0aG91dCBhIG5hdGl2ZSBhZGRvbiwgd2hpY2ggaXMgZmFyIHRvb1xuICogaGVhdnkgYSBkZXBlbmRlbmN5IGZvciB0aGlzIGhhcm5lc3MuXG4gKlxuICogU28gd2UgdXNlIHRoZSBvbmUgY3Jvc3MtcGxhdGZvcm0gcmVzb3VyY2UgdGhlIGtlcm5lbCAqZG9lcyogcmVjbGFpbVxuICogZGV0ZXJtaW5pc3RpY2FsbHkgb24gcHJvY2VzcyBkZWF0aDogYSBzb2NrZXQuIFRoZSBoYXJuZXNzIGxpc3RlbnMgb24gYVxuICogbG9vcGJhY2sgcG9ydCBhbmQgdGhlIGluc3RhbmNlJ3MgcmVuZGVyZXIgY29ubmVjdHMgdG8gaXQuIEhvd2V2ZXIgdGhlIGhhcm5lc3NcbiAqIGRpZXMgXHUyMDE0IGNsZWFubHksIGBTSUdLSUxMYGVkLCBvciBjcmFzaGVkIFx1MjAxNCB0aGUga2VybmVsIGNsb3NlcyBpdHMgZW5kIGFuZCB0aGVcbiAqIHJlbmRlcmVyIHNlZXMgYGNsb3NlYC4gTm8gcG9sbGluZywgbm8gaGVhcnRiZWF0IGludGVydmFsLCBubyB0aW1lb3V0IHRvIHR1bmUuXG4gKlxuICogKipBIGNsb3NlIGlzIGEgcXVlc3Rpb24sIG5vdCBhIHZlcmRpY3QuKiogQSBzb2NrZXQgY2xvc2luZyBpcyBub3QgdGhlIHNhbWVcbiAqIGV2ZW50IGFzIGEgcHJvY2VzcyBkeWluZywgYW5kIHRyZWF0aW5nIHRoZW0gYXMgaWRlbnRpY2FsIGRlc3Ryb3llZCBoZWFsdGh5XG4gKiBpbnN0YW5jZXM6IG1lYXN1cmVkIG9uIDIwMjYtMDktMDUsIGEgcmVuZGVyZXIncyBpZGxlIGxpdmVuZXNzIHNvY2tldCBzZW50XG4gKiBgRklOYCBvbiBpdHMgb3duIFx1MjAxNCAzIG1pbiAxMyBzIGludG8gb25lIHJ1biwgMTEgbWluIDU2IHMgaW50byBhbm90aGVyIFx1MjAxNCB3aGlsZVxuICogdGhlIGhhcm5lc3Mgd2FzIHN0aWxsIGxpc3RlbmluZyBhbmQgd2VudCBvbiB3b3JraW5nIGZvciBhbm90aGVyIDE0IG1pbnV0ZXMuXG4gKiBFdmVyeSB0ZXN0IGZpbGUgc2NoZWR1bGVkIGFmdGVyIHRoZSBkZWF0aCB0aGVuIGZhaWxlZCBpbiB0ZW5zIG9mIG1pbGxpc2Vjb25kc1xuICogd2l0aCBgRUNPTk5SRUZVU0VEYCBvbiB0aGUgZGVhZCBDRFAgcG9ydDsgdGhlIHdvcnN0IHJ1biByZXBvcnRlZCAxNTYgc3VjaFxuICogZmFpbHVyZXMgYWNyb3NzIDIxIGZpbGVzLCBub3Qgb25lIG9mIHRoZW0gYSB0ZXN0IHJlc3VsdC4gV2h5IGFuIGlkbGUgdW5yZWYnZFxuICogbG9vcGJhY2sgc29ja2V0IGluIGFuIEVsZWN0cm9uIHJlbmRlcmVyIGRvZXMgdGhhdCBpcyBub3QgZXN0YWJsaXNoZWQsIGFuZCBkb2VzXG4gKiBub3QgbmVlZCB0byBiZTogdGhlIGxpZmV0aW1lcyB2YXJ5IHJ1biB0byBydW4sIHNvIG5vIGZpeGVkIHRpbWVvdXQgZXhwbGFpbnMgaXQuXG4gKlxuICogU28gdGhlIGBjbG9zZWAgaGFuZGxlciAqKnZlcmlmaWVzIGJlZm9yZSBkZXN0cm95aW5nKio6IGl0IHJlY29ubmVjdHMgdG8gdGhlXG4gKiBzYW1lIGxvb3BiYWNrIHBvcnQuIEEgaGFybmVzcyB0aGF0IGlzIGFsaXZlIGlzIHN0aWxsIGxpc3RlbmluZywgc28gdGhlXG4gKiByZWNvbm5lY3Qgc3VjY2VlZHMgYW5kIHRoZSBuZXcgc29ja2V0IGJlY29tZXMgdGhlIGxpdmVuZXNzIHRva2VuOyBvbmx5IHdoZW5cbiAqIG5vdGhpbmcgYW5zd2VycyBhZnRlciBhIGZldyB0cmllcyBcdTIwMTQgd2hhdCBhIGRlYWQgaGFybmVzcyBhY3R1YWxseSBsb29rcyBsaWtlIFx1MjAxNFxuICogaXMgdGhlIHdpbmRvdyBkZXN0cm95ZWQuIFRoZSBsZWFrIHRoZSB3YXRjaGRvZyBleGlzdHMgdG8gcHJldmVudCBpcyBzdGlsbFxuICogcHJldmVudGVkLCBhbmQgdGhlIG1lYXN1cmVkIHJlY292ZXJ5IGlzIDExIG1zLlxuICpcbiAqIEEgcmVjb25uZWN0IHJhdGhlciB0aGFuIGEgY2hlY2sgb24gdGhlIGhhcm5lc3MncyBwcm9jZXNzIGlkLCBiZWNhdXNlIGl0IHByb3Zlc1xuICogdGhlIHRoaW5nIHRoZSB3YXRjaGRvZyBhY3R1YWxseSBkZXBlbmRzIG9uIFx1MjAxNCB0aGUgbGl2ZW5lc3Mgc2VydmVyIHN0aWxsIHNlcnZpbmdcbiAqIFx1MjAxNCBhbmQgaXQgc3RheXMgY29ycmVjdCBhZ2FpbnN0IGEgKmJ1c3kqIGhhcm5lc3M6IHRoZSBrZXJuZWwgY29tcGxldGVzIGFcbiAqIGxvb3BiYWNrIGhhbmRzaGFrZSBvdXQgb2YgdGhlIGxpc3RlbiBiYWNrbG9nIGV2ZW4gd2hpbGUgTm9kZSdzIGV2ZW50IGxvb3AgaXNcbiAqIGJsb2NrZWQuIEl0cyBvbmUgcmVzaWR1YWwgYW1iaWd1aXR5IGlzIGFjY2VwdGVkOiBhIHJlY29ubmVjdCBwcm92ZXMgKnNvbWV0aGluZypcbiAqIGlzIGxpc3RlbmluZyBvbiB0aGF0IGVwaGVtZXJhbCBwb3J0LCBub3QgdGhhdCBpdCBpcyBvdXJzLiBUaGUgcHJvYmUgZm9sbG93cyB0aGVcbiAqIGNsb3NlIGJ5IG1pbGxpc2Vjb25kcywgc28gYW5vdGhlciBwcm9jZXNzIHdpbm5pbmcgdGhhdCBleGFjdCBwb3J0IGluIGJldHdlZW4gaXNcbiAqIG5vdCBhIHJpc2sgd29ydGggYSBoYW5kc2hha2UgcHJvdG9jb2wuXG4gKlxuICogRGVsaWJlcmF0ZWx5IGZhaWwtb3BlbjogdGhlIHJlbmRlcmVyIG9ubHkgYXJtcyB0aGUgZGVzdHJveSBwYXRoIGFmdGVyIHRoZVxuICogY29ubmVjdGlvbiBpcyBhY3R1YWxseSBlc3RhYmxpc2hlZC4gQSB3YXRjaGRvZyB0aGF0IGNhbm5vdCByZWFjaCB0aGUgaGFybmVzc1xuICogbGVhdmVzIHRoZSBpbnN0YW5jZSBydW5uaW5nIHJhdGhlciB0aGFuIGtpbGxpbmcgYSB3aW5kb3cgdGhlIGRldmVsb3BlciBpc1xuICogd29ya2luZyBpbi5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7IFNlcnZlciB9IGZyb20gJ25vZGU6bmV0JztcblxuaW1wb3J0IHsgY3JlYXRlU2VydmVyIH0gZnJvbSAnbm9kZTpuZXQnO1xuXG4vKipcbiAqIEEgbGlzdGVuaW5nIGxvb3BiYWNrIHNlcnZlciB3aG9zZSBhY2NlcHRlZCBjb25uZWN0aW9ucyBhY3QgYXMgbGl2ZW5lc3MgdG9rZW5zXG4gKiBmb3IgdGhlIGhhcm5lc3MgcHJvY2Vzcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQYXJlbnRMaXZlbmVzc1NlcnZlciB7XG4gIC8qKlxuICAgKiBTdG9wcyBsaXN0ZW5pbmcuXG4gICAqXG4gICAqIE5vZGUga2VlcHMgYWxyZWFkeS1hY2NlcHRlZCBjb25uZWN0aW9ucyBhbGl2ZSBhY3Jvc3MgYSBgY2xvc2UoKWAsIHNvIHRoaXNcbiAgICogZG9lcyBub3QgYnkgaXRzZWxmIHNpZ25hbCB0aGUgcmVuZGVyZXIgXHUyMDE0IHRoZSBrZXJuZWwgcmVjbGFpbWluZyB0aGUgc29ja2V0IG9uXG4gICAqIHByb2Nlc3MgZGVhdGggaXMgd2hhdCBkb2VzLiBXaGF0IGl0IGRvZXMgZ3VhcmFudGVlIGlzIHRoYXQgYSB3YXRjaGRvZyBwcm9iZVxuICAgKiBhcnJpdmluZyBhZnRlcndhcmRzIGlzIHJlZnVzZWQsIHdoaWNoIGlzIHRoZSBhbnN3ZXIgYSB0b3JuLWRvd24gaGFybmVzc1xuICAgKiBzaG91bGQgZ2l2ZS5cbiAgICovXG4gIGNsb3NlKCk6IHZvaWQ7XG5cbiAgLyoqXG4gIFRoZSBsb29wYmFjayBwb3J0IHRoZSByZW5kZXJlciB3YXRjaGRvZyBzaG91bGQgY29ubmVjdCBiYWNrIHRvLlxuICAgKi9cbiAgcmVhZG9ubHkgcG9ydDogbnVtYmVyO1xufVxuXG4vKipcbiAqIExvb3BiYWNrIGhvc3QgdGhlIGxpdmVuZXNzIHNlcnZlciBiaW5kcyB0by4gTmV2ZXIgZXhwb3NlZCBvZmYtbWFjaGluZS5cbiAqL1xuZXhwb3J0IGNvbnN0IFBBUkVOVF9MSVZFTkVTU19IT1NUID0gJzEyNy4wLjAuMSc7XG5cbi8qKlxuICogSG93IG1hbnkgdGltZXMgdGhlIHdhdGNoZG9nIHByb2JlcyB0aGUgbG9vcGJhY2sgcG9ydCBiZWZvcmUgY29uY2x1ZGluZyB0aGVcbiAqIGhhcm5lc3MgaXMgZ29uZS5cbiAqXG4gKiBNb3JlIHRoYW4gb25lLCBzbyBhIHNpbmdsZSB0cmFuc2llbnQgcmVmdXNhbCBjYW5ub3QgY29zdCBhIHdob2xlIHJ1bjsgc21hbGwsXG4gKiBiZWNhdXNlIGV2ZXJ5IGF0dGVtcHQgaXMgYSBsb29wYmFjayBjb25uZWN0IHRoYXQgZWl0aGVyIGNvbXBsZXRlcyBvciBpc1xuICogcmVmdXNlZCBpbW1lZGlhdGVseSwgYW5kIGFuIGluc3RhbmNlIHdob3NlIGhhcm5lc3MgcmVhbGx5IGRpZCBkaWUgc2hvdWxkIG5vdFxuICogbGluZ2VyLlxuICovXG5jb25zdCBSRUNPTk5FQ1RfQVRURU1QVF9MSU1JVCA9IDM7XG5cbi8qKlxuICogSG93IGxvbmcgdGhlIHdhdGNoZG9nIHdhaXRzIGJldHdlZW4gcHJvYmVzLlxuICpcbiAqIExvbmcgZW5vdWdoIHRvIG91dGxhc3QgYSBtb21lbnRhcnkgcmVmdXNhbCwgc2hvcnQgZW5vdWdoIHRoYXQgZXhoYXVzdGluZyB0aGVcbiAqIHdob2xlIGJ1ZGdldCBzdGlsbCBkZXN0cm95cyBhbiBvcnBoYW5lZCB3aW5kb3cgaW5zaWRlIGEgc2Vjb25kLlxuICovXG5jb25zdCBSRUNPTk5FQ1RfREVMQVlfSU5fTUlMTElTRUNPTkRTID0gMjUwO1xuXG4vKipcbiAqIEJ1aWxkcyB0aGUgZXhwcmVzc2lvbiBldmFsdWF0ZWQgaW4gdGhlIG93bmVkIGluc3RhbmNlJ3MgcmVuZGVyZXIgdG8gYXJtIHRoZVxuICogd2F0Y2hkb2cuXG4gKlxuICogV3JpdHRlbiBpbiBFUzUgc3R5bGUgKGB2YXJgLCBgZnVuY3Rpb25gKSB3aXRoIG5vIG9wdGlvbmFsIGNoYWluaW5nLCBtYXRjaGluZ1xuICoge0BsaW5rIERJU01JU1NfVFJVU1RfRElBTE9HX0VYUFJ9OiB0aGUgc2FtZSBleHByZXNzaW9uIGhhcyB0byBwYXJzZSBvbiB0aGVcbiAqIENocm9taXVtIDgwLWVyYSByZW5kZXJlcnMgb2YgdGhlIG9sZGVzdCBzdXBwb3J0ZWQgT2JzaWRpYW4gdmVyc2lvbnMgKEwyNikuXG4gKlxuICogQXJtaW5nIGlzIGlkZW1wb3RlbnQgXHUyMDE0IGEgc2Vjb25kIGV2YWx1YXRpb24gZmluZHMgdGhlIHN0b3JlZCBzb2NrZXQgYW5kXG4gKiByZXR1cm5zIHdpdGhvdXQgb3BlbmluZyBhbm90aGVyIGNvbm5lY3Rpb24sIHNvIGEgcmV0cmllZCByZWFkaW5lc3MgcGFzcyBkb2VzXG4gKiBub3QgcGlsZSB1cCBzb2NrZXRzLlxuICpcbiAqIEBwYXJhbSBwb3J0IC0gVGhlIGxvb3BiYWNrIHBvcnQgcmV0dXJuZWQgYnkge0BsaW5rIHN0YXJ0UGFyZW50TGl2ZW5lc3NTZXJ2ZXJ9LlxuICogQHJldHVybnMgVGhlIGV4cHJlc3Npb24gdG8gZXZhbHVhdGUsIHlpZWxkaW5nIGAnYXJtZWQnYCwgYCdhbHJlYWR5LWFybWVkJ2AsIG9yIGAndW5hdmFpbGFibGUnYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkUGFyZW50TGl2ZW5lc3NXYXRjaGRvZ0V4cHJlc3Npb24ocG9ydDogbnVtYmVyKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAoZnVuY3Rpb24oKSB7XG4gIHZhciBGTEFHID0gJ19fb2JzaWRpYW5JbnRlZ3JhdGlvblRlc3RpbmdQYXJlbnRMaXZlbmVzcyc7XG4gIGlmICh3aW5kb3dbRkxBR10pIHsgcmV0dXJuICdhbHJlYWR5LWFybWVkJzsgfVxuICB2YXIgbmV0O1xuICB0cnkge1xuICAgIG5ldCA9IHdpbmRvdy5yZXF1aXJlKCdub2RlOm5ldCcpO1xuICB9IGNhdGNoIChub2RlUHJlZml4RXJyb3IpIHtcbiAgICB0cnkge1xuICAgICAgbmV0ID0gd2luZG93LnJlcXVpcmUoJ25ldCcpO1xuICAgIH0gY2F0Y2ggKGJhcmVQcmVmaXhFcnJvcikge1xuICAgICAgcmV0dXJuICd1bmF2YWlsYWJsZSc7XG4gICAgfVxuICB9XG4gIHZhciBQT1JUID0gJHtTdHJpbmcocG9ydCl9O1xuICB2YXIgSE9TVCA9ICcke1BBUkVOVF9MSVZFTkVTU19IT1NUfSc7XG4gIHZhciBSRUNPTk5FQ1RfQVRURU1QVF9MSU1JVCA9ICR7U3RyaW5nKFJFQ09OTkVDVF9BVFRFTVBUX0xJTUlUKX07XG4gIHZhciBSRUNPTk5FQ1RfREVMQVlfSU5fTUlMTElTRUNPTkRTID0gJHtTdHJpbmcoUkVDT05ORUNUX0RFTEFZX0lOX01JTExJU0VDT05EUyl9O1xuICB2YXIgc29ja2V0ID0gbmV0LmNvbm5lY3QoUE9SVCwgSE9TVCk7XG4gIHdpbmRvd1tGTEFHXSA9IHNvY2tldDtcbiAgdmFyIGlzQ29ubmVjdGVkID0gZmFsc2U7XG4gIHNvY2tldC5vbignY29ubmVjdCcsIGZ1bmN0aW9uKCkgeyBpc0Nvbm5lY3RlZCA9IHRydWU7IH0pO1xuICBzb2NrZXQub24oJ2Vycm9yJywgZnVuY3Rpb24oKSB7IC8qIFRoZSBjbG9zZSBoYW5kbGVyIGJlbG93IGRlY2lkZXMgd2hhdCBhbiBlcnJvciBtZWFudC4gKi8gfSk7XG4gIHNvY2tldC5vbignY2xvc2UnLCBmdW5jdGlvbigpIHtcbiAgICAvKiBGYWlsIG9wZW46IGEgY29ubmVjdGlvbiB0aGF0IG5ldmVyIGVzdGFibGlzaGVkIGlzIG5vIGV2aWRlbmNlIHRoZSBoYXJuZXNzIGRpZWQuICovXG4gICAgaWYgKCFpc0Nvbm5lY3RlZCkgeyByZXR1cm47IH1cbiAgICByZWNvbm5lY3QoMSk7XG4gIH0pO1xuICByZXR1cm4gJ2FybWVkJztcblxuICAvKiBBIGNsb3NlIG9ubHkgYXNrcyB0aGUgcXVlc3Rpb24uIFJlY29ubmVjdGluZyBhbnN3ZXJzIGl0LiAqL1xuICBmdW5jdGlvbiByZWNvbm5lY3QoYXR0ZW1wdCkge1xuICAgIHZhciBkaWRDb25uZWN0ID0gZmFsc2U7XG4gICAgdmFyIHByb2JlID0gbmV0LmNvbm5lY3QoUE9SVCwgSE9TVCk7XG4gICAgcHJvYmUub24oJ2Nvbm5lY3QnLCBmdW5jdGlvbigpIHtcbiAgICAgIC8qIFNvbWVvbmUgaXMgc3RpbGwgbGlzdGVuaW5nLCBzbyB0aGUgaGFybmVzcyBpcyBhbGl2ZS4gVGhpcyBpcyB0aGUgbmV3IHRva2VuLiAqL1xuICAgICAgZGlkQ29ubmVjdCA9IHRydWU7XG4gICAgICB3aW5kb3dbRkxBR10gPSBwcm9iZTtcbiAgICAgIHByb2JlLm9uKCdjbG9zZScsIGZ1bmN0aW9uKCkgeyByZWNvbm5lY3QoMSk7IH0pO1xuICAgIH0pO1xuICAgIHByb2JlLm9uKCdlcnJvcicsIGZ1bmN0aW9uKCkge1xuICAgICAgLypcbiAgICAgICAqIFRoaXMgaGFuZGxlciBvdXRsaXZlcyB0aGUgY29ubmVjdCwgc28gaXQgZG91YmxlcyBhcyB0aGUgYWRvcHRlZCBzb2NrZXQnc1xuICAgICAgICogZXJyb3IgaGFuZGxlci4gT25jZSBjb25uZWN0ZWQsIGFuIGVycm9yIHNheXMgbm90aGluZyBhYm91dCB0aGUgaGFybmVzcyBcdTIwMTRcbiAgICAgICAqIHRoZSBjbG9zZSB0aGF0IGZvbGxvd3MgaXQgcmUtcnVucyB0aGUgcHJvYmUuXG4gICAgICAgKi9cbiAgICAgIGlmIChkaWRDb25uZWN0KSB7IHJldHVybjsgfVxuICAgICAgaWYgKGF0dGVtcHQgPCBSRUNPTk5FQ1RfQVRURU1QVF9MSU1JVCkge1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgeyByZWNvbm5lY3QoYXR0ZW1wdCArIDEpOyB9LCBSRUNPTk5FQ1RfREVMQVlfSU5fTUlMTElTRUNPTkRTKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgLyogTm90aGluZyBhbnN3ZXJlZCBhZnRlciBzZXZlcmFsIHRyaWVzOiB0aGUgaGFybmVzcyByZWFsbHkgaXMgZ29uZS4gKi9cbiAgICAgIGRlc3Ryb3lXaW5kb3coKTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGRlc3Ryb3lXaW5kb3coKSB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvdy5lbGVjdHJvbldpbmRvdy5kZXN0cm95KCk7XG4gICAgfSBjYXRjaCAoZGVzdHJveUVycm9yKSB7XG4gICAgICB3aW5kb3cuY2xvc2UoKTtcbiAgICB9XG4gIH1cbn0pKClgO1xufVxuXG4vKipcbiAqIFN0YXJ0cyB0aGUgbG9vcGJhY2sgbGl2ZW5lc3Mgc2VydmVyIHRoZSBvd25lZCBpbnN0YW5jZSdzIHJlbmRlcmVyIGNvbm5lY3RzXG4gKiBiYWNrIHRvLlxuICpcbiAqIFRoZSBzZXJ2ZXIgYW5kIGV2ZXJ5IGFjY2VwdGVkIHNvY2tldCBhcmUgYHVucmVmYGVkLCBzbyBob2xkaW5nIGEgd2F0Y2hkb2dcbiAqIGNvbm5lY3Rpb24gb3BlbiBuZXZlciBrZWVwcyB0aGUgaGFybmVzcyBwcm9jZXNzIGFsaXZlIG9uIGl0cyBvd24gXHUyMDE0IHRoZVxuICogY29ubmVjdGlvbiBpcyBhIHRva2VuIHRoZSBrZXJuZWwgcmVjbGFpbXMsIG5vdCB3b3JrIHRvIHdhaXQgb24uXG4gKlxuICogQHJldHVybnMgQSB7QGxpbmsgUHJvbWlzZX0gcmVzb2x2aW5nIHRvIHRoZSBsaXN0ZW5pbmcge0BsaW5rIFBhcmVudExpdmVuZXNzU2VydmVyfS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHN0YXJ0UGFyZW50TGl2ZW5lc3NTZXJ2ZXIoKTogUHJvbWlzZTxQYXJlbnRMaXZlbmVzc1NlcnZlcj4ge1xuICBjb25zdCBzZXJ2ZXIgPSBjcmVhdGVTZXJ2ZXIoKHNvY2tldCkgPT4ge1xuICAgIHNvY2tldC51bnJlZigpO1xuICAgIC8vIFRoZSBjb25uZWN0aW9uIGNhcnJpZXMgbm8gZGF0YSBcdTIwMTQgaXQgZXhpc3RzIG9ubHkgc28gaXRzIGNsb3NlIGlzIG9ic2VydmFibGUuXG4gICAgc29ja2V0Lm9uKCdlcnJvcicsICgpID0+IHtcbiAgICAgIC8vIEEgcmVuZGVyZXIgdG9ybiBkb3duIG1pZC1jb25uZWN0aW9uIHJlc2V0cyByYXRoZXIgdGhhbiBjbG9zZXM7IG5vdCBhbiBlcnJvciBoZXJlLlxuICAgIH0pO1xuICB9KTtcbiAgc2VydmVyLnVucmVmKCk7XG5cbiAgY29uc3QgcG9ydCA9IGF3YWl0IGxpc3Rlbk9uRnJlZUxvb3BiYWNrUG9ydChzZXJ2ZXIpO1xuICByZXR1cm4ge1xuICAgIGNsb3NlKCk6IHZvaWQge1xuICAgICAgc2VydmVyLmNsb3NlKCk7XG4gICAgfSxcbiAgICBwb3J0XG4gIH07XG59XG5cbi8qKlxuICogQmluZHMgdGhlIHNlcnZlciB0byBhbiBlcGhlbWVyYWwgbG9vcGJhY2sgcG9ydCBhbmQgcmVwb3J0cyB3aGljaCBvbmUgaXQgZ290LlxuICpcbiAqIEBwYXJhbSBzZXJ2ZXIgLSBUaGUgc2VydmVyIHRvIGJpbmQuXG4gKiBAcmV0dXJucyBBIHtAbGluayBQcm9taXNlfSByZXNvbHZpbmcgdG8gdGhlIGFzc2lnbmVkIHBvcnQuXG4gKiBAdGhyb3dzIElmIHRoZSBzZXJ2ZXIgcmVwb3J0cyBhbiBlcnJvciBiZWZvcmUgbGlzdGVuaW5nLCBvciBiaW5kcyB0byBhIHBpcGUgcmF0aGVyIHRoYW4gYSBwb3J0LlxuICovXG5hc3luYyBmdW5jdGlvbiBsaXN0ZW5PbkZyZWVMb29wYmFja1BvcnQoc2VydmVyOiBTZXJ2ZXIpOiBQcm9taXNlPG51bWJlcj4ge1xuICByZXR1cm4gbmV3IFByb21pc2U8bnVtYmVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgc2VydmVyLm9uY2UoJ2Vycm9yJywgcmVqZWN0KTtcbiAgICBzZXJ2ZXIubGlzdGVuKDAsIFBBUkVOVF9MSVZFTkVTU19IT1NULCAoKSA9PiB7XG4gICAgICBjb25zdCBhZGRyZXNzID0gc2VydmVyLmFkZHJlc3MoKTtcbiAgICAgIGlmIChhZGRyZXNzID09PSBudWxsIHx8IHR5cGVvZiBhZGRyZXNzID09PSAnc3RyaW5nJykge1xuICAgICAgICBzZXJ2ZXIuY2xvc2UoKTtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignRmFpbGVkIHRvIGRldGVybWluZSB0aGUgcGFyZW50LWxpdmVuZXNzIHBvcnQuJykpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICByZXNvbHZlKGFkZHJlc3MucG9ydCk7XG4gICAgfSk7XG4gIH0pO1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIkFBZ0VBLFNBQVMsb0JBQW9CO0FBMkJ0QixNQUFNLHVCQUF1QjtBQVdwQyxNQUFNLDBCQUEwQjtBQVFoQyxNQUFNLGtDQUFrQztBQWlCakMsU0FBUyxzQ0FBc0MsTUFBc0I7QUFDMUUsU0FBTztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGVBYU0sT0FBTyxJQUFJLENBQUM7QUFBQSxnQkFDWCxvQkFBb0I7QUFBQSxrQ0FDRixPQUFPLHVCQUF1QixDQUFDO0FBQUEsMENBQ3ZCLE9BQU8sK0JBQStCLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQStDakY7QUFZQSxlQUFzQiw0QkFBMkQ7QUFDL0UsUUFBTSxTQUFTLGFBQWEsQ0FBQyxXQUFXO0FBQ3RDLFdBQU8sTUFBTTtBQUViLFdBQU8sR0FBRyxTQUFTLE1BQU07QUFBQSxJQUV6QixDQUFDO0FBQUEsRUFDSCxDQUFDO0FBQ0QsU0FBTyxNQUFNO0FBRWIsUUFBTSxPQUFPLE1BQU0seUJBQXlCLE1BQU07QUFDbEQsU0FBTztBQUFBLElBQ0wsUUFBYztBQUNaLGFBQU8sTUFBTTtBQUFBLElBQ2Y7QUFBQSxJQUNBO0FBQUEsRUFDRjtBQUNGO0FBU0EsZUFBZSx5QkFBeUIsUUFBaUM7QUFDdkUsU0FBTyxJQUFJLFFBQWdCLENBQUMsU0FBUyxXQUFXO0FBQzlDLFdBQU8sS0FBSyxTQUFTLE1BQU07QUFDM0IsV0FBTyxPQUFPLEdBQUcsc0JBQXNCLE1BQU07QUFDM0MsWUFBTSxVQUFVLE9BQU8sUUFBUTtBQUMvQixVQUFJLFlBQVksUUFBUSxPQUFPLFlBQVksVUFBVTtBQUNuRCxlQUFPLE1BQU07QUFDYixlQUFPLElBQUksTUFBTSwrQ0FBK0MsQ0FBQztBQUNqRTtBQUFBLE1BQ0Y7QUFDQSxjQUFRLFFBQVEsSUFBSTtBQUFBLElBQ3RCLENBQUM7QUFBQSxFQUNILENBQUM7QUFDSDsiLAogICJuYW1lcyI6IFtdCn0K
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @file
3
+ *
4
+ * Pure helpers for answering "which process is still holding this port?".
5
+ *
6
+ * A teardown that cannot answer that question can only re-issue the same kill at
7
+ * the same PID, which is no escalation at all: the PID the harness holds is the
8
+ * shell wrapper it spawned, and what survives is whatever that wrapper's tree
9
+ * walk failed to reach. The port, by contrast, is direct evidence — a socket
10
+ * still answering on 4723 after this run killed the server it started belongs to
11
+ * that server.
12
+ *
13
+ * Kept separate from the integration-only `transport-factory` so the parsing
14
+ * stays unit-testable; the factory shells out to `netstat` / `lsof`.
15
+ */
16
+ /**
17
+ * Parameters for {@link parseWindowsNetstatPids}.
18
+ */
19
+ export interface ParseWindowsNetstatPidsParams {
20
+ /**
21
+ Raw stdout of `netstat -ano`.
22
+ */
23
+ readonly netstatOutput: string;
24
+ /**
25
+ The local port whose listener is wanted.
26
+ */
27
+ readonly port: number;
28
+ }
29
+ /**
30
+ * Parses `lsof -ti tcp:<port>` output, which is already one PID per line.
31
+ *
32
+ * @param lsofOutput - Raw stdout of the `lsof` query.
33
+ * @returns The distinct PIDs, in listed order.
34
+ */
35
+ export declare function parsePosixLsofPids(lsofOutput: string): number[];
36
+ /**
37
+ * Parses `netstat -ano` output for the PIDs **listening** on a port.
38
+ *
39
+ * Only `TCP` rows in the `LISTENING` state count: an established connection *to*
40
+ * the port belongs to a client, not to the server that must die, and the `UDP`
41
+ * rows have no state column at all. The same server appears twice when it binds
42
+ * both IPv4 and IPv6, so PIDs are de-duplicated.
43
+ *
44
+ * @param params - The listing output and the port to match.
45
+ * @returns The distinct listening PIDs, in listed order.
46
+ */
47
+ export declare function parseWindowsNetstatPids(params: ParseWindowsNetstatPidsParams): number[];
@@ -0,0 +1,36 @@
1
+ const LISTENING_STATE = "LISTENING";
2
+ const RADIX_DECIMAL = 10;
3
+ const TCP_PROTOCOL = "TCP";
4
+ const WHITESPACE_PATTERN = /\s+/;
5
+ function parsePosixLsofPids(lsofOutput) {
6
+ const pids = [];
7
+ for (const line of lsofOutput.split("\n")) {
8
+ const pid = Number.parseInt(line.trim(), RADIX_DECIMAL);
9
+ if (Number.isNaN(pid) || pids.includes(pid)) {
10
+ continue;
11
+ }
12
+ pids.push(pid);
13
+ }
14
+ return pids;
15
+ }
16
+ function parseWindowsNetstatPids(params) {
17
+ const localAddressSuffix = `:${String(params.port)}`;
18
+ const pids = [];
19
+ for (const rawLine of params.netstatOutput.split("\n")) {
20
+ const [protocol = "", localAddress = "", , state = "", rawPid = ""] = rawLine.trim().split(WHITESPACE_PATTERN);
21
+ if (protocol !== TCP_PROTOCOL || state !== LISTENING_STATE || !localAddress.endsWith(localAddressSuffix)) {
22
+ continue;
23
+ }
24
+ const pid = Number.parseInt(rawPid, RADIX_DECIMAL);
25
+ if (Number.isNaN(pid) || pids.includes(pid)) {
26
+ continue;
27
+ }
28
+ pids.push(pid);
29
+ }
30
+ return pids;
31
+ }
32
+ export {
33
+ parsePosixLsofPids,
34
+ parseWindowsNetstatPids
35
+ };
36
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3BvcnQtb3duZXIudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qKlxuICogQGZpbGVcbiAqXG4gKiBQdXJlIGhlbHBlcnMgZm9yIGFuc3dlcmluZyBcIndoaWNoIHByb2Nlc3MgaXMgc3RpbGwgaG9sZGluZyB0aGlzIHBvcnQ/XCIuXG4gKlxuICogQSB0ZWFyZG93biB0aGF0IGNhbm5vdCBhbnN3ZXIgdGhhdCBxdWVzdGlvbiBjYW4gb25seSByZS1pc3N1ZSB0aGUgc2FtZSBraWxsIGF0XG4gKiB0aGUgc2FtZSBQSUQsIHdoaWNoIGlzIG5vIGVzY2FsYXRpb24gYXQgYWxsOiB0aGUgUElEIHRoZSBoYXJuZXNzIGhvbGRzIGlzIHRoZVxuICogc2hlbGwgd3JhcHBlciBpdCBzcGF3bmVkLCBhbmQgd2hhdCBzdXJ2aXZlcyBpcyB3aGF0ZXZlciB0aGF0IHdyYXBwZXIncyB0cmVlXG4gKiB3YWxrIGZhaWxlZCB0byByZWFjaC4gVGhlIHBvcnQsIGJ5IGNvbnRyYXN0LCBpcyBkaXJlY3QgZXZpZGVuY2UgXHUyMDE0IGEgc29ja2V0XG4gKiBzdGlsbCBhbnN3ZXJpbmcgb24gNDcyMyBhZnRlciB0aGlzIHJ1biBraWxsZWQgdGhlIHNlcnZlciBpdCBzdGFydGVkIGJlbG9uZ3MgdG9cbiAqIHRoYXQgc2VydmVyLlxuICpcbiAqIEtlcHQgc2VwYXJhdGUgZnJvbSB0aGUgaW50ZWdyYXRpb24tb25seSBgdHJhbnNwb3J0LWZhY3RvcnlgIHNvIHRoZSBwYXJzaW5nXG4gKiBzdGF5cyB1bml0LXRlc3RhYmxlOyB0aGUgZmFjdG9yeSBzaGVsbHMgb3V0IHRvIGBuZXRzdGF0YCAvIGBsc29mYC5cbiAqL1xuXG4vKipcbiAqIFBhcmFtZXRlcnMgZm9yIHtAbGluayBwYXJzZVdpbmRvd3NOZXRzdGF0UGlkc30uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUGFyc2VXaW5kb3dzTmV0c3RhdFBpZHNQYXJhbXMge1xuICAvKipcbiAgUmF3IHN0ZG91dCBvZiBgbmV0c3RhdCAtYW5vYC5cbiAgICovXG4gIHJlYWRvbmx5IG5ldHN0YXRPdXRwdXQ6IHN0cmluZztcblxuICAvKipcbiAgVGhlIGxvY2FsIHBvcnQgd2hvc2UgbGlzdGVuZXIgaXMgd2FudGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgcG9ydDogbnVtYmVyO1xufVxuXG5jb25zdCBMSVNURU5JTkdfU1RBVEUgPSAnTElTVEVOSU5HJztcbmNvbnN0IFJBRElYX0RFQ0lNQUwgPSAxMDtcbmNvbnN0IFRDUF9QUk9UT0NPTCA9ICdUQ1AnO1xuY29uc3QgV0hJVEVTUEFDRV9QQVRURVJOID0gL1xccysvO1xuXG4vKipcbiAqIFBhcnNlcyBgbHNvZiAtdGkgdGNwOjxwb3J0PmAgb3V0cHV0LCB3aGljaCBpcyBhbHJlYWR5IG9uZSBQSUQgcGVyIGxpbmUuXG4gKlxuICogQHBhcmFtIGxzb2ZPdXRwdXQgLSBSYXcgc3Rkb3V0IG9mIHRoZSBgbHNvZmAgcXVlcnkuXG4gKiBAcmV0dXJucyBUaGUgZGlzdGluY3QgUElEcywgaW4gbGlzdGVkIG9yZGVyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VQb3NpeExzb2ZQaWRzKGxzb2ZPdXRwdXQ6IHN0cmluZyk6IG51bWJlcltdIHtcbiAgY29uc3QgcGlkczogbnVtYmVyW10gPSBbXTtcblxuICBmb3IgKGNvbnN0IGxpbmUgb2YgbHNvZk91dHB1dC5zcGxpdCgnXFxuJykpIHtcbiAgICBjb25zdCBwaWQgPSBOdW1iZXIucGFyc2VJbnQobGluZS50cmltKCksIFJBRElYX0RFQ0lNQUwpO1xuICAgIGlmIChOdW1iZXIuaXNOYU4ocGlkKSB8fCBwaWRzLmluY2x1ZGVzKHBpZCkpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIHBpZHMucHVzaChwaWQpO1xuICB9XG5cbiAgcmV0dXJuIHBpZHM7XG59XG5cbi8qKlxuICogUGFyc2VzIGBuZXRzdGF0IC1hbm9gIG91dHB1dCBmb3IgdGhlIFBJRHMgKipsaXN0ZW5pbmcqKiBvbiBhIHBvcnQuXG4gKlxuICogT25seSBgVENQYCByb3dzIGluIHRoZSBgTElTVEVOSU5HYCBzdGF0ZSBjb3VudDogYW4gZXN0YWJsaXNoZWQgY29ubmVjdGlvbiAqdG8qXG4gKiB0aGUgcG9ydCBiZWxvbmdzIHRvIGEgY2xpZW50LCBub3QgdG8gdGhlIHNlcnZlciB0aGF0IG11c3QgZGllLCBhbmQgdGhlIGBVRFBgXG4gKiByb3dzIGhhdmUgbm8gc3RhdGUgY29sdW1uIGF0IGFsbC4gVGhlIHNhbWUgc2VydmVyIGFwcGVhcnMgdHdpY2Ugd2hlbiBpdCBiaW5kc1xuICogYm90aCBJUHY0IGFuZCBJUHY2LCBzbyBQSURzIGFyZSBkZS1kdXBsaWNhdGVkLlxuICpcbiAqIEBwYXJhbSBwYXJhbXMgLSBUaGUgbGlzdGluZyBvdXRwdXQgYW5kIHRoZSBwb3J0IHRvIG1hdGNoLlxuICogQHJldHVybnMgVGhlIGRpc3RpbmN0IGxpc3RlbmluZyBQSURzLCBpbiBsaXN0ZWQgb3JkZXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVdpbmRvd3NOZXRzdGF0UGlkcyhwYXJhbXM6IFBhcnNlV2luZG93c05ldHN0YXRQaWRzUGFyYW1zKTogbnVtYmVyW10ge1xuICBjb25zdCBsb2NhbEFkZHJlc3NTdWZmaXggPSBgOiR7U3RyaW5nKHBhcmFtcy5wb3J0KX1gO1xuICBjb25zdCBwaWRzOiBudW1iZXJbXSA9IFtdO1xuXG4gIGZvciAoY29uc3QgcmF3TGluZSBvZiBwYXJhbXMubmV0c3RhdE91dHB1dC5zcGxpdCgnXFxuJykpIHtcbiAgICBjb25zdCBbcHJvdG9jb2wgPSAnJywgbG9jYWxBZGRyZXNzID0gJycsICwgc3RhdGUgPSAnJywgcmF3UGlkID0gJyddID0gcmF3TGluZS50cmltKCkuc3BsaXQoV0hJVEVTUEFDRV9QQVRURVJOKTtcbiAgICBpZiAocHJvdG9jb2wgIT09IFRDUF9QUk9UT0NPTCB8fCBzdGF0ZSAhPT0gTElTVEVOSU5HX1NUQVRFIHx8ICFsb2NhbEFkZHJlc3MuZW5kc1dpdGgobG9jYWxBZGRyZXNzU3VmZml4KSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgY29uc3QgcGlkID0gTnVtYmVyLnBhcnNlSW50KHJhd1BpZCwgUkFESVhfREVDSU1BTCk7XG4gICAgaWYgKE51bWJlci5pc05hTihwaWQpIHx8IHBpZHMuaW5jbHVkZXMocGlkKSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgcGlkcy5wdXNoKHBpZCk7XG4gIH1cblxuICByZXR1cm4gcGlkcztcbn1cbiJdLAogICJtYXBwaW5ncyI6ICJBQStCQSxNQUFNLGtCQUFrQjtBQUN4QixNQUFNLGdCQUFnQjtBQUN0QixNQUFNLGVBQWU7QUFDckIsTUFBTSxxQkFBcUI7QUFRcEIsU0FBUyxtQkFBbUIsWUFBOEI7QUFDL0QsUUFBTSxPQUFpQixDQUFDO0FBRXhCLGFBQVcsUUFBUSxXQUFXLE1BQU0sSUFBSSxHQUFHO0FBQ3pDLFVBQU0sTUFBTSxPQUFPLFNBQVMsS0FBSyxLQUFLLEdBQUcsYUFBYTtBQUN0RCxRQUFJLE9BQU8sTUFBTSxHQUFHLEtBQUssS0FBSyxTQUFTLEdBQUcsR0FBRztBQUMzQztBQUFBLElBQ0Y7QUFFQSxTQUFLLEtBQUssR0FBRztBQUFBLEVBQ2Y7QUFFQSxTQUFPO0FBQ1Q7QUFhTyxTQUFTLHdCQUF3QixRQUFpRDtBQUN2RixRQUFNLHFCQUFxQixJQUFJLE9BQU8sT0FBTyxJQUFJLENBQUM7QUFDbEQsUUFBTSxPQUFpQixDQUFDO0FBRXhCLGFBQVcsV0FBVyxPQUFPLGNBQWMsTUFBTSxJQUFJLEdBQUc7QUFDdEQsVUFBTSxDQUFDLFdBQVcsSUFBSSxlQUFlLElBQUksRUFBRSxRQUFRLElBQUksU0FBUyxFQUFFLElBQUksUUFBUSxLQUFLLEVBQUUsTUFBTSxrQkFBa0I7QUFDN0csUUFBSSxhQUFhLGdCQUFnQixVQUFVLG1CQUFtQixDQUFDLGFBQWEsU0FBUyxrQkFBa0IsR0FBRztBQUN4RztBQUFBLElBQ0Y7QUFFQSxVQUFNLE1BQU0sT0FBTyxTQUFTLFFBQVEsYUFBYTtBQUNqRCxRQUFJLE9BQU8sTUFBTSxHQUFHLEtBQUssS0FBSyxTQUFTLEdBQUcsR0FBRztBQUMzQztBQUFBLElBQ0Y7QUFFQSxTQUFLLEtBQUssR0FBRztBQUFBLEVBQ2Y7QUFFQSxTQUFPO0FBQ1Q7IiwKICAibmFtZXMiOiBbXQp9Cg==
@@ -0,0 +1,83 @@
1
+ /**
2
+ * @file
3
+ *
4
+ * Attaches output capture and exit observation to a spawned child process.
5
+ *
6
+ * A long-running child spawned with piped stdio needs three things done to it,
7
+ * and getting any of them wrong is its own bug: its pipes must be **drained**
8
+ * (a full OS pipe buffer blocks the writer — a chatty renderer would hang the
9
+ * app it belongs to), its output must be kept **bounded** (an hour of logs is
10
+ * not a diagnostic), and its `exit` / `error` must be **recorded** so a caller
11
+ * that later finds the process unreachable can say why instead of guessing.
12
+ *
13
+ * Extracted so the state machine is unit-testable: the launchers that use it
14
+ * (`obsidian-instance.ts`, and the emulator/Appium spawns in
15
+ * `transport-factory.ts`) are integration-time glue excluded from unit tests,
16
+ * which is how the owned Obsidian instance came to be spawned `stdio: 'ignore'`
17
+ * with no `exit` listener at all — its death was unobservable by construction.
18
+ */
19
+ import type { ChildProcess } from 'node:child_process';
20
+ import type { ProcessExitInfo } from './process-exit-message.mjs';
21
+ /**
22
+ * Parameters for {@link attachProcessCapture}.
23
+ */
24
+ export interface AttachProcessCaptureParams {
25
+ /**
26
+ * How many characters of the most recent output to keep. Older output is
27
+ * dropped from the front as new output arrives.
28
+ */
29
+ readonly maxOutputLengthInCharacters: number;
30
+ /**
31
+ * Called for every chunk as it arrives, for callers that want the output
32
+ * **live** (logged as the process runs) rather than only as a post-mortem
33
+ * tail. Fires regardless of {@link ProcessCapture.stopCapture}, which freezes
34
+ * the retained tail and nothing else.
35
+ */
36
+ readonly onChunk?: ((chunk: ProcessOutputChunk) => void) | undefined;
37
+ }
38
+ /**
39
+ * A child process's captured output and exit status.
40
+ */
41
+ export interface ProcessCapture {
42
+ /**
43
+ Returns the exit / spawn-failure details once the process is no longer running, otherwise `undefined`.
44
+ */
45
+ readExitInfo: () => ProcessExitInfo | undefined;
46
+ /**
47
+ Returns the captured stdout+stderr, bounded to the most recent output.
48
+ */
49
+ readOutput: () => string;
50
+ /**
51
+ * Stops accumulating output, freezing the tail at what has arrived so far.
52
+ * Call once startup has succeeded and the tail has served its purpose.
53
+ *
54
+ * The `data` listeners stay attached deliberately, so the pipes keep draining
55
+ * for the rest of the process's life.
56
+ */
57
+ stopCapture: () => void;
58
+ }
59
+ /**
60
+ * One chunk of a child process's output, and which stream it came from.
61
+ */
62
+ export interface ProcessOutputChunk {
63
+ /**
64
+ The stream the chunk was written to.
65
+ */
66
+ readonly stream: 'stderr' | 'stdout';
67
+ /**
68
+ The chunk's text.
69
+ */
70
+ readonly text: string;
71
+ }
72
+ /**
73
+ * Attaches output capture and exit observation to an already-spawned process.
74
+ *
75
+ * Tolerates a process spawned without pipes (`stdio: 'ignore'` leaves
76
+ * `stdout` / `stderr` `null`): the exit half still works, and the captured
77
+ * output stays empty.
78
+ *
79
+ * @param child - The spawned process.
80
+ * @param params - The tail budget, and an optional live-output callback.
81
+ * @returns Readers for the captured output and the exit status.
82
+ */
83
+ export declare function attachProcessCapture(child: ChildProcess, params: AttachProcessCaptureParams): ProcessCapture;
@@ -0,0 +1,38 @@
1
+ function attachProcessCapture(child, params) {
2
+ const { maxOutputLengthInCharacters, onChunk } = params;
3
+ let capturedOutput = "";
4
+ let exitInfo;
5
+ let isCapturing = true;
6
+ attachStream(child.stdout, "stdout");
7
+ attachStream(child.stderr, "stderr");
8
+ child.once("exit", (code, signal) => {
9
+ exitInfo = { code, signal };
10
+ });
11
+ child.once("error", (error) => {
12
+ exitInfo = { code: null, signal: null, spawnError: error.message };
13
+ });
14
+ return {
15
+ readExitInfo: () => exitInfo,
16
+ readOutput: () => capturedOutput,
17
+ stopCapture: () => {
18
+ isCapturing = false;
19
+ }
20
+ };
21
+ function attachStream(stream, name) {
22
+ if (!stream) {
23
+ return;
24
+ }
25
+ stream.on("data", (chunk) => {
26
+ const text = chunk.toString();
27
+ onChunk?.({ stream: name, text });
28
+ if (isCapturing) {
29
+ capturedOutput = (capturedOutput + text).slice(-maxOutputLengthInCharacters);
30
+ }
31
+ });
32
+ stream.unref?.();
33
+ }
34
+ }
35
+ export {
36
+ attachProcessCapture
37
+ };
38
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3Byb2Nlc3MtY2FwdHVyZS50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIEF0dGFjaGVzIG91dHB1dCBjYXB0dXJlIGFuZCBleGl0IG9ic2VydmF0aW9uIHRvIGEgc3Bhd25lZCBjaGlsZCBwcm9jZXNzLlxuICpcbiAqIEEgbG9uZy1ydW5uaW5nIGNoaWxkIHNwYXduZWQgd2l0aCBwaXBlZCBzdGRpbyBuZWVkcyB0aHJlZSB0aGluZ3MgZG9uZSB0byBpdCxcbiAqIGFuZCBnZXR0aW5nIGFueSBvZiB0aGVtIHdyb25nIGlzIGl0cyBvd24gYnVnOiBpdHMgcGlwZXMgbXVzdCBiZSAqKmRyYWluZWQqKlxuICogKGEgZnVsbCBPUyBwaXBlIGJ1ZmZlciBibG9ja3MgdGhlIHdyaXRlciBcdTIwMTQgYSBjaGF0dHkgcmVuZGVyZXIgd291bGQgaGFuZyB0aGVcbiAqIGFwcCBpdCBiZWxvbmdzIHRvKSwgaXRzIG91dHB1dCBtdXN0IGJlIGtlcHQgKipib3VuZGVkKiogKGFuIGhvdXIgb2YgbG9ncyBpc1xuICogbm90IGEgZGlhZ25vc3RpYyksIGFuZCBpdHMgYGV4aXRgIC8gYGVycm9yYCBtdXN0IGJlICoqcmVjb3JkZWQqKiBzbyBhIGNhbGxlclxuICogdGhhdCBsYXRlciBmaW5kcyB0aGUgcHJvY2VzcyB1bnJlYWNoYWJsZSBjYW4gc2F5IHdoeSBpbnN0ZWFkIG9mIGd1ZXNzaW5nLlxuICpcbiAqIEV4dHJhY3RlZCBzbyB0aGUgc3RhdGUgbWFjaGluZSBpcyB1bml0LXRlc3RhYmxlOiB0aGUgbGF1bmNoZXJzIHRoYXQgdXNlIGl0XG4gKiAoYG9ic2lkaWFuLWluc3RhbmNlLnRzYCwgYW5kIHRoZSBlbXVsYXRvci9BcHBpdW0gc3Bhd25zIGluXG4gKiBgdHJhbnNwb3J0LWZhY3RvcnkudHNgKSBhcmUgaW50ZWdyYXRpb24tdGltZSBnbHVlIGV4Y2x1ZGVkIGZyb20gdW5pdCB0ZXN0cyxcbiAqIHdoaWNoIGlzIGhvdyB0aGUgb3duZWQgT2JzaWRpYW4gaW5zdGFuY2UgY2FtZSB0byBiZSBzcGF3bmVkIGBzdGRpbzogJ2lnbm9yZSdgXG4gKiB3aXRoIG5vIGBleGl0YCBsaXN0ZW5lciBhdCBhbGwgXHUyMDE0IGl0cyBkZWF0aCB3YXMgdW5vYnNlcnZhYmxlIGJ5IGNvbnN0cnVjdGlvbi5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7IENoaWxkUHJvY2VzcyB9IGZyb20gJ25vZGU6Y2hpbGRfcHJvY2Vzcyc7XG5pbXBvcnQgdHlwZSB7IFJlYWRhYmxlIH0gZnJvbSAnbm9kZTpzdHJlYW0nO1xuXG5pbXBvcnQgdHlwZSB7IFByb2Nlc3NFeGl0SW5mbyB9IGZyb20gJy4vcHJvY2Vzcy1leGl0LW1lc3NhZ2UubWpzJztcblxuLyoqXG4gKiBQYXJhbWV0ZXJzIGZvciB7QGxpbmsgYXR0YWNoUHJvY2Vzc0NhcHR1cmV9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEF0dGFjaFByb2Nlc3NDYXB0dXJlUGFyYW1zIHtcbiAgLyoqXG4gICAqIEhvdyBtYW55IGNoYXJhY3RlcnMgb2YgdGhlIG1vc3QgcmVjZW50IG91dHB1dCB0byBrZWVwLiBPbGRlciBvdXRwdXQgaXNcbiAgICogZHJvcHBlZCBmcm9tIHRoZSBmcm9udCBhcyBuZXcgb3V0cHV0IGFycml2ZXMuXG4gICAqL1xuICByZWFkb25seSBtYXhPdXRwdXRMZW5ndGhJbkNoYXJhY3RlcnM6IG51bWJlcjtcblxuICAvKipcbiAgICogQ2FsbGVkIGZvciBldmVyeSBjaHVuayBhcyBpdCBhcnJpdmVzLCBmb3IgY2FsbGVycyB0aGF0IHdhbnQgdGhlIG91dHB1dFxuICAgKiAqKmxpdmUqKiAobG9nZ2VkIGFzIHRoZSBwcm9jZXNzIHJ1bnMpIHJhdGhlciB0aGFuIG9ubHkgYXMgYSBwb3N0LW1vcnRlbVxuICAgKiB0YWlsLiBGaXJlcyByZWdhcmRsZXNzIG9mIHtAbGluayBQcm9jZXNzQ2FwdHVyZS5zdG9wQ2FwdHVyZX0sIHdoaWNoIGZyZWV6ZXNcbiAgICogdGhlIHJldGFpbmVkIHRhaWwgYW5kIG5vdGhpbmcgZWxzZS5cbiAgICovXG4gIHJlYWRvbmx5IG9uQ2h1bms/OiAoKGNodW5rOiBQcm9jZXNzT3V0cHV0Q2h1bmspID0+IHZvaWQpIHwgdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIEEgY2hpbGQgcHJvY2VzcydzIGNhcHR1cmVkIG91dHB1dCBhbmQgZXhpdCBzdGF0dXMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUHJvY2Vzc0NhcHR1cmUge1xuICAvKipcbiAgUmV0dXJucyB0aGUgZXhpdCAvIHNwYXduLWZhaWx1cmUgZGV0YWlscyBvbmNlIHRoZSBwcm9jZXNzIGlzIG5vIGxvbmdlciBydW5uaW5nLCBvdGhlcndpc2UgYHVuZGVmaW5lZGAuXG4gICAqL1xuICByZWFkRXhpdEluZm86ICgpID0+IFByb2Nlc3NFeGl0SW5mbyB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgUmV0dXJucyB0aGUgY2FwdHVyZWQgc3Rkb3V0K3N0ZGVyciwgYm91bmRlZCB0byB0aGUgbW9zdCByZWNlbnQgb3V0cHV0LlxuICAgKi9cbiAgcmVhZE91dHB1dDogKCkgPT4gc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBTdG9wcyBhY2N1bXVsYXRpbmcgb3V0cHV0LCBmcmVlemluZyB0aGUgdGFpbCBhdCB3aGF0IGhhcyBhcnJpdmVkIHNvIGZhci5cbiAgICogQ2FsbCBvbmNlIHN0YXJ0dXAgaGFzIHN1Y2NlZWRlZCBhbmQgdGhlIHRhaWwgaGFzIHNlcnZlZCBpdHMgcHVycG9zZS5cbiAgICpcbiAgICogVGhlIGBkYXRhYCBsaXN0ZW5lcnMgc3RheSBhdHRhY2hlZCBkZWxpYmVyYXRlbHksIHNvIHRoZSBwaXBlcyBrZWVwIGRyYWluaW5nXG4gICAqIGZvciB0aGUgcmVzdCBvZiB0aGUgcHJvY2VzcydzIGxpZmUuXG4gICAqL1xuICBzdG9wQ2FwdHVyZTogKCkgPT4gdm9pZDtcbn1cblxuLyoqXG4gKiBPbmUgY2h1bmsgb2YgYSBjaGlsZCBwcm9jZXNzJ3Mgb3V0cHV0LCBhbmQgd2hpY2ggc3RyZWFtIGl0IGNhbWUgZnJvbS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQcm9jZXNzT3V0cHV0Q2h1bmsge1xuICAvKipcbiAgVGhlIHN0cmVhbSB0aGUgY2h1bmsgd2FzIHdyaXR0ZW4gdG8uXG4gICAqL1xuICByZWFkb25seSBzdHJlYW06ICdzdGRlcnInIHwgJ3N0ZG91dCc7XG5cbiAgLyoqXG4gIFRoZSBjaHVuaydzIHRleHQuXG4gICAqL1xuICByZWFkb25seSB0ZXh0OiBzdHJpbmc7XG59XG5cbi8qKlxuICogVGhlIGB1bnJlZmAgYSBwaXBlZCBzdGRpbyBzdHJlYW0gY2FycmllcyB0aHJvdWdoIGl0cyB1bmRlcmx5aW5nIHNvY2tldCwgd2hpY2hcbiAqIGBSZWFkYWJsZWAgYWxvbmUgZG9lcyBub3QgZGVjbGFyZS5cbiAqL1xuaW50ZXJmYWNlIFN0cmVhbVdpdGhVbnJlZiB7XG4gIHVucmVmOiAoKSA9PiB2b2lkO1xufVxuXG4vKipcbiAqIEF0dGFjaGVzIG91dHB1dCBjYXB0dXJlIGFuZCBleGl0IG9ic2VydmF0aW9uIHRvIGFuIGFscmVhZHktc3Bhd25lZCBwcm9jZXNzLlxuICpcbiAqIFRvbGVyYXRlcyBhIHByb2Nlc3Mgc3Bhd25lZCB3aXRob3V0IHBpcGVzIChgc3RkaW86ICdpZ25vcmUnYCBsZWF2ZXNcbiAqIGBzdGRvdXRgIC8gYHN0ZGVycmAgYG51bGxgKTogdGhlIGV4aXQgaGFsZiBzdGlsbCB3b3JrcywgYW5kIHRoZSBjYXB0dXJlZFxuICogb3V0cHV0IHN0YXlzIGVtcHR5LlxuICpcbiAqIEBwYXJhbSBjaGlsZCAtIFRoZSBzcGF3bmVkIHByb2Nlc3MuXG4gKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHRhaWwgYnVkZ2V0LCBhbmQgYW4gb3B0aW9uYWwgbGl2ZS1vdXRwdXQgY2FsbGJhY2suXG4gKiBAcmV0dXJucyBSZWFkZXJzIGZvciB0aGUgY2FwdHVyZWQgb3V0cHV0IGFuZCB0aGUgZXhpdCBzdGF0dXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhdHRhY2hQcm9jZXNzQ2FwdHVyZShjaGlsZDogQ2hpbGRQcm9jZXNzLCBwYXJhbXM6IEF0dGFjaFByb2Nlc3NDYXB0dXJlUGFyYW1zKTogUHJvY2Vzc0NhcHR1cmUge1xuICBjb25zdCB7IG1heE91dHB1dExlbmd0aEluQ2hhcmFjdGVycywgb25DaHVuayB9ID0gcGFyYW1zO1xuXG4gIGxldCBjYXB0dXJlZE91dHB1dCA9ICcnO1xuICBsZXQgZXhpdEluZm86IFByb2Nlc3NFeGl0SW5mbyB8IHVuZGVmaW5lZDtcbiAgbGV0IGlzQ2FwdHVyaW5nID0gdHJ1ZTtcblxuICBhdHRhY2hTdHJlYW0oY2hpbGQuc3Rkb3V0LCAnc3Rkb3V0Jyk7XG4gIGF0dGFjaFN0cmVhbShjaGlsZC5zdGRlcnIsICdzdGRlcnInKTtcblxuICBjaGlsZC5vbmNlKCdleGl0JywgKGNvZGU6IG51bGwgfCBudW1iZXIsIHNpZ25hbDogTm9kZUpTLlNpZ25hbHMgfCBudWxsKSA9PiB7XG4gICAgZXhpdEluZm8gPSB7IGNvZGUsIHNpZ25hbCB9O1xuICB9KTtcblxuICAvKlxuICAgKiBBIHNwYXduIGZhaWx1cmUgKGUuZy4gRU5PRU5UIGZvciBhIG1pc3NpbmcgYmluYXJ5KSBlbWl0cyAnZXJyb3InLCBub3RcbiAgICogJ2V4aXQnLiBSZWNvcmQgaXQgYXMgYSBzeW50aGV0aWMgZXhpdCBzbyBhIGNhbGxlciBwb2xsaW5nIGZvciByZWFkaW5lc3MgY2FuXG4gICAqIGZhaWwgZmFzdCBpbnN0ZWFkIG9mIHNwaW5uaW5nIG91dCBpdHMgd2hvbGUgYnVkZ2V0IGFnYWluc3QgYSBwcm9jZXNzIHRoYXRcbiAgICogbmV2ZXIgZXhpc3RlZC5cbiAgICovXG4gIGNoaWxkLm9uY2UoJ2Vycm9yJywgKGVycm9yOiBFcnJvcikgPT4ge1xuICAgIGV4aXRJbmZvID0geyBjb2RlOiBudWxsLCBzaWduYWw6IG51bGwsIHNwYXduRXJyb3I6IGVycm9yLm1lc3NhZ2UgfTtcbiAgfSk7XG5cbiAgcmV0dXJuIHtcbiAgICByZWFkRXhpdEluZm86ICgpID0+IGV4aXRJbmZvLFxuICAgIHJlYWRPdXRwdXQ6ICgpID0+IGNhcHR1cmVkT3V0cHV0LFxuICAgIHN0b3BDYXB0dXJlOiAoKTogdm9pZCA9PiB7XG4gICAgICBpc0NhcHR1cmluZyA9IGZhbHNlO1xuICAgIH1cbiAgfTtcblxuICBmdW5jdGlvbiBhdHRhY2hTdHJlYW0oc3RyZWFtOiBudWxsIHwgUmVhZGFibGUsIG5hbWU6IFByb2Nlc3NPdXRwdXRDaHVua1snc3RyZWFtJ10pOiB2b2lkIHtcbiAgICBpZiAoIXN0cmVhbSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHN0cmVhbS5vbignZGF0YScsIChjaHVuazogQnVmZmVyKSA9PiB7XG4gICAgICBjb25zdCB0ZXh0ID0gY2h1bmsudG9TdHJpbmcoKTtcbiAgICAgIG9uQ2h1bms/Lih7IHN0cmVhbTogbmFtZSwgdGV4dCB9KTtcbiAgICAgIGlmIChpc0NhcHR1cmluZykge1xuICAgICAgICBjYXB0dXJlZE91dHB1dCA9IChjYXB0dXJlZE91dHB1dCArIHRleHQpLnNsaWNlKC1tYXhPdXRwdXRMZW5ndGhJbkNoYXJhY3RlcnMpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgLypcbiAgICAgKiBgY2hpbGQudW5yZWYoKWAgb25seSByZWxlYXNlcyB0aGUgcHJvY2VzcyBoYW5kbGU7IHRoZSBzdGRpbyBwaXBlcyBhcmVcbiAgICAgKiBzZXBhcmF0ZSBoYW5kbGVzIHRoYXQga2VlcCB0aGUgZXZlbnQgbG9vcCBhbGl2ZSBvbiB0aGVpciBvd24uIEEgaGFybmVzc1xuICAgICAqIHRoYXQgcGlwZXMgYSBkZXRhY2hlZCBjaGlsZCdzIG91dHB1dCB3b3VsZCB0aGVuIHJlZnVzZSB0byBleGl0IHVudGlsIHRoYXRcbiAgICAgKiBjaGlsZCBkaWVkIFx1MjAxNCB0aGUgb3Bwb3NpdGUgb2Ygd2hhdCBgZGV0YWNoZWRgICsgYHVucmVmYCB3YXMgYXNrZWQgZm9yLlxuICAgICAqXG4gICAgICogYHVucmVmYCBsaXZlcyBvbiB0aGUgdW5kZXJseWluZyBzb2NrZXQgcmF0aGVyIHRoYW4gb24gYFJlYWRhYmxlYCwgc28gaXQgaXNcbiAgICAgKiByZWFjaGVkIHN0cnVjdHVyYWxseTogYSBzdHJlYW0gdGhhdCBkb2VzIG5vdCBjYXJyeSBvbmUgc2ltcGx5IHNraXBzIHRoaXMuXG4gICAgICovXG4gICAgKHN0cmVhbSBhcyBQYXJ0aWFsPFN0cmVhbVdpdGhVbnJlZj4pLnVucmVmPy4oKTtcbiAgfVxufVxuIl0sCiAgIm1hcHBpbmdzIjogIkFBcUdPLFNBQVMscUJBQXFCLE9BQXFCLFFBQW9EO0FBQzVHLFFBQU0sRUFBRSw2QkFBNkIsUUFBUSxJQUFJO0FBRWpELE1BQUksaUJBQWlCO0FBQ3JCLE1BQUk7QUFDSixNQUFJLGNBQWM7QUFFbEIsZUFBYSxNQUFNLFFBQVEsUUFBUTtBQUNuQyxlQUFhLE1BQU0sUUFBUSxRQUFRO0FBRW5DLFFBQU0sS0FBSyxRQUFRLENBQUMsTUFBcUIsV0FBa0M7QUFDekUsZUFBVyxFQUFFLE1BQU0sT0FBTztBQUFBLEVBQzVCLENBQUM7QUFRRCxRQUFNLEtBQUssU0FBUyxDQUFDLFVBQWlCO0FBQ3BDLGVBQVcsRUFBRSxNQUFNLE1BQU0sUUFBUSxNQUFNLFlBQVksTUFBTSxRQUFRO0FBQUEsRUFDbkUsQ0FBQztBQUVELFNBQU87QUFBQSxJQUNMLGNBQWMsTUFBTTtBQUFBLElBQ3BCLFlBQVksTUFBTTtBQUFBLElBQ2xCLGFBQWEsTUFBWTtBQUN2QixvQkFBYztBQUFBLElBQ2hCO0FBQUEsRUFDRjtBQUVBLFdBQVMsYUFBYSxRQUF5QixNQUEwQztBQUN2RixRQUFJLENBQUMsUUFBUTtBQUNYO0FBQUEsSUFDRjtBQUVBLFdBQU8sR0FBRyxRQUFRLENBQUMsVUFBa0I7QUFDbkMsWUFBTSxPQUFPLE1BQU0sU0FBUztBQUM1QixnQkFBVSxFQUFFLFFBQVEsTUFBTSxLQUFLLENBQUM7QUFDaEMsVUFBSSxhQUFhO0FBQ2YsMEJBQWtCLGlCQUFpQixNQUFNLE1BQU0sQ0FBQywyQkFBMkI7QUFBQSxNQUM3RTtBQUFBLElBQ0YsQ0FBQztBQVdELElBQUMsT0FBb0MsUUFBUTtBQUFBLEVBQy9DO0FBQ0Y7IiwKICAibmFtZXMiOiBbXQp9Cg==
@@ -1,14 +1,32 @@
1
1
  /**
2
2
  * @file
3
3
  *
4
- * Pure builder for the diagnostic message describing an auto-started child
5
- * process (the Android emulator or the Appium server) that died during startup,
6
- * appending the captured output tail when available.
4
+ * Pure builders for the diagnostic message describing an auto-started child
5
+ * process (the Android emulator or the Appium server) that failed during
6
+ * startup, appending the captured output tail when available.
7
+ *
8
+ * A startup fails two ways — the process **dies**, or it **hangs** past a
9
+ * budget — and the captured tail is equally the explanation in both. So the
10
+ * tail-appending half is its own export, used by the timeout throws that once
11
+ * reported only the budget they blew.
7
12
  *
8
13
  * Kept separate from the integration-only `transport-factory` (excluded from
9
14
  * unit tests) so the message formatting stays unit-testable — the launchers
10
15
  * themselves spawn real processes.
11
16
  */
17
+ /**
18
+ * Parameters for {@link appendProcessOutputTail}.
19
+ */
20
+ export interface AppendProcessOutputTailParams {
21
+ /**
22
+ The captured stdout+stderr tail (empty when none was captured).
23
+ */
24
+ readonly output: string;
25
+ /**
26
+ Label for the captured output section (e.g. `"Emulator output"`).
27
+ */
28
+ readonly outputLabel: string;
29
+ }
12
30
  /**
13
31
  * Parameters for {@link buildProcessExitMessage}.
14
32
  */
@@ -51,6 +69,22 @@ export interface ProcessExitInfo {
51
69
  */
52
70
  readonly spawnError?: string;
53
71
  }
72
+ /**
73
+ * Appends a process's captured output tail to a message, when there is one.
74
+ *
75
+ * Split out of {@link buildProcessExitMessage} so the **timeout** failures can
76
+ * carry the tail too. A process that dies gets its output attached; one that
77
+ * hangs used to get `No new emulator device appeared within 300000ms.` and
78
+ * nothing else — even though the line that explains it (`FATAL | Running
79
+ * multiple emulators with the same AVD is an experimental feature`) had already
80
+ * been captured. The emulator writing its own diagnosis is worth nothing if the
81
+ * harness reads it on only one of the two ways a startup can fail.
82
+ *
83
+ * @param message - The failure message to extend.
84
+ * @param params - The captured tail and its label.
85
+ * @returns The message, with the tail appended when non-empty.
86
+ */
87
+ export declare function appendProcessOutputTail(message: string, params: AppendProcessOutputTailParams): string;
54
88
  /**
55
89
  * Builds a descriptive error message for an auto-started child process that
56
90
  * exited (or failed to spawn) during startup, appending the captured output
@@ -1,12 +1,16 @@
1
+ function appendProcessOutputTail(message, params) {
2
+ const trimmedOutput = params.output.trim();
3
+ if (trimmedOutput.length === 0) {
4
+ return message;
5
+ }
6
+ return `${message}
7
+
8
+ ${params.outputLabel} (tail):
9
+ ${trimmedOutput}`;
10
+ }
1
11
  function buildProcessExitMessage(params) {
2
12
  const { exitInfo, output, outputLabel, subject } = params;
3
- const reason = resolveReason(exitInfo);
4
- const trimmedOutput = output.trim();
5
- const details = trimmedOutput.length > 0 ? `
6
-
7
- ${outputLabel} (tail):
8
- ${trimmedOutput}` : "";
9
- return `${subject} ${reason} during startup.${details}`;
13
+ return appendProcessOutputTail(`${subject} ${resolveReason(exitInfo)} during startup.`, { output, outputLabel });
10
14
  }
11
15
  function resolveReason(exitInfo) {
12
16
  if (exitInfo.spawnError !== void 0) {
@@ -18,6 +22,7 @@ function resolveReason(exitInfo) {
18
22
  return `exited prematurely with code ${exitInfo.code === null ? "(null)" : String(exitInfo.code)}`;
19
23
  }
20
24
  export {
25
+ appendProcessOutputTail,
21
26
  buildProcessExitMessage
22
27
  };
23
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3Byb2Nlc3MtZXhpdC1tZXNzYWdlLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBmaWxlXG4gKlxuICogUHVyZSBidWlsZGVyIGZvciB0aGUgZGlhZ25vc3RpYyBtZXNzYWdlIGRlc2NyaWJpbmcgYW4gYXV0by1zdGFydGVkIGNoaWxkXG4gKiBwcm9jZXNzICh0aGUgQW5kcm9pZCBlbXVsYXRvciBvciB0aGUgQXBwaXVtIHNlcnZlcikgdGhhdCBkaWVkIGR1cmluZyBzdGFydHVwLFxuICogYXBwZW5kaW5nIHRoZSBjYXB0dXJlZCBvdXRwdXQgdGFpbCB3aGVuIGF2YWlsYWJsZS5cbiAqXG4gKiBLZXB0IHNlcGFyYXRlIGZyb20gdGhlIGludGVncmF0aW9uLW9ubHkgYHRyYW5zcG9ydC1mYWN0b3J5YCAoZXhjbHVkZWQgZnJvbVxuICogdW5pdCB0ZXN0cykgc28gdGhlIG1lc3NhZ2UgZm9ybWF0dGluZyBzdGF5cyB1bml0LXRlc3RhYmxlIFx1MjAxNCB0aGUgbGF1bmNoZXJzXG4gKiB0aGVtc2VsdmVzIHNwYXduIHJlYWwgcHJvY2Vzc2VzLlxuICovXG5cbi8qKlxuICogUGFyYW1ldGVycyBmb3Ige0BsaW5rIGJ1aWxkUHJvY2Vzc0V4aXRNZXNzYWdlfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBCdWlsZFByb2Nlc3NFeGl0TWVzc2FnZVBhcmFtcyB7XG4gIC8qKlxuICBUaGUgcHJvY2VzcydzIGV4aXQgLyBzcGF3bi1mYWlsdXJlIGRldGFpbHMuXG4gICAqL1xuICByZWFkb25seSBleGl0SW5mbzogUHJvY2Vzc0V4aXRJbmZvO1xuXG4gIC8qKlxuICBUaGUgY2FwdHVyZWQgc3Rkb3V0K3N0ZGVyciB0YWlsIChlbXB0eSB3aGVuIG5vbmUgd2FzIGNhcHR1cmVkKS5cbiAgICovXG4gIHJlYWRvbmx5IG91dHB1dDogc3RyaW5nO1xuXG4gIC8qKlxuICBMYWJlbCBmb3IgdGhlIGNhcHR1cmVkIG91dHB1dCBzZWN0aW9uIChlLmcuIGBcIkVtdWxhdG9yIG91dHB1dFwiYCkuXG4gICAqL1xuICByZWFkb25seSBvdXRwdXRMYWJlbDogc3RyaW5nO1xuXG4gIC8qKlxuICBIdW1hbi1yZWFkYWJsZSBzdWJqZWN0IG9mIHRoZSBwcm9jZXNzIChlLmcuIGBcIkFuZHJvaWQgZW11bGF0b3JcImApLlxuICAgKi9cbiAgcmVhZG9ubHkgc3ViamVjdDogc3RyaW5nO1xufVxuXG4vKipcbiAqIERldGFpbHMgb2YgYSBzcGF3bmVkIGNoaWxkIHByb2Nlc3MgdGhhdCBoYXMgZXhpdGVkIG9yIGZhaWxlZCB0byBzcGF3bi5cbiAqXG4gKiBBIG5vcm1hbCBleGl0IHNldHMgYGNvZGVgL2BzaWduYWxgIChleGFjdGx5IG9uZSBpcyBub24tYG51bGxgKTsgYSBzcGF3blxuICogZmFpbHVyZSAoZS5nLiBgRU5PRU5UYCBmb3IgYSBtaXNzaW5nIGJpbmFyeSkgbGVhdmVzIGJvdGggYG51bGxgIGFuZCBzZXRzXG4gKiBgc3Bhd25FcnJvcmAgdG8gdGhlIGZhaWx1cmUgbWVzc2FnZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQcm9jZXNzRXhpdEluZm8ge1xuICAvKipcbiAgRXhpdCBjb2RlLCBvciBgbnVsbGAgd2hlbiB0ZXJtaW5hdGVkIGJ5IGEgc2lnbmFsIG9yIHdoZW4gaXQgZmFpbGVkIHRvIHNwYXduLlxuICAgKi9cbiAgcmVhZG9ubHkgY29kZTogbnVsbCB8IG51bWJlcjtcblxuICAvKipcbiAgVGVybWluYXRpbmcgc2lnbmFsLCBvciBgbnVsbGAgd2hlbiBpdCBleGl0ZWQgbm9ybWFsbHkgb3IgZmFpbGVkIHRvIHNwYXduLlxuICAgKi9cbiAgcmVhZG9ubHkgc2lnbmFsOiBOb2RlSlMuU2lnbmFscyB8IG51bGw7XG5cbiAgLyoqXG4gIFRoZSBzcGF3bi1mYWlsdXJlIG1lc3NhZ2Ugd2hlbiB0aGUgcHJvY2VzcyBuZXZlciBzdGFydGVkIChlLmcuIGBFTk9FTlRgKSwgb3RoZXJ3aXNlIGFic2VudC5cbiAgICovXG4gIHJlYWRvbmx5IHNwYXduRXJyb3I/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogQnVpbGRzIGEgZGVzY3JpcHRpdmUgZXJyb3IgbWVzc2FnZSBmb3IgYW4gYXV0by1zdGFydGVkIGNoaWxkIHByb2Nlc3MgdGhhdFxuICogZXhpdGVkIChvciBmYWlsZWQgdG8gc3Bhd24pIGR1cmluZyBzdGFydHVwLCBhcHBlbmRpbmcgdGhlIGNhcHR1cmVkIG91dHB1dFxuICogdGFpbCB3aGVuIGF2YWlsYWJsZS5cbiAqXG4gKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHN1YmplY3QsIGV4aXQgZGV0YWlscywgYW5kIGNhcHR1cmVkIG91dHB1dC5cbiAqIEByZXR1cm5zIEEgaHVtYW4tcmVhZGFibGUgZXJyb3IgbWVzc2FnZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkUHJvY2Vzc0V4aXRNZXNzYWdlKHBhcmFtczogQnVpbGRQcm9jZXNzRXhpdE1lc3NhZ2VQYXJhbXMpOiBzdHJpbmcge1xuICBjb25zdCB7IGV4aXRJbmZvLCBvdXRwdXQsIG91dHB1dExhYmVsLCBzdWJqZWN0IH0gPSBwYXJhbXM7XG5cbiAgY29uc3QgcmVhc29uID0gcmVzb2x2ZVJlYXNvbihleGl0SW5mbyk7XG4gIGNvbnN0IHRyaW1tZWRPdXRwdXQgPSBvdXRwdXQudHJpbSgpO1xuICBjb25zdCBkZXRhaWxzID0gdHJpbW1lZE91dHB1dC5sZW5ndGggPiAwXG4gICAgPyBgXFxuXFxuJHtvdXRwdXRMYWJlbH0gKHRhaWwpOlxcbiR7dHJpbW1lZE91dHB1dH1gXG4gICAgOiAnJztcbiAgcmV0dXJuIGAke3N1YmplY3R9ICR7cmVhc29ufSBkdXJpbmcgc3RhcnR1cC4ke2RldGFpbHN9YDtcbn1cblxuLyoqXG4gKiBEZXNjcmliZXMgd2h5IHRoZSBwcm9jZXNzIGlzIG5vIGxvbmdlciBydW5uaW5nLlxuICpcbiAqIEBwYXJhbSBleGl0SW5mbyAtIFRoZSBleGl0IC8gc3Bhd24tZmFpbHVyZSBkZXRhaWxzLlxuICogQHJldHVybnMgVGhlIHJlYXNvbiBjbGF1c2UuXG4gKi9cbmZ1bmN0aW9uIHJlc29sdmVSZWFzb24oZXhpdEluZm86IFByb2Nlc3NFeGl0SW5mbyk6IHN0cmluZyB7XG4gIGlmIChleGl0SW5mby5zcGF3bkVycm9yICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gYGZhaWxlZCB0byBzdGFydCAoJHtleGl0SW5mby5zcGF3bkVycm9yfSlgO1xuICB9XG4gIGlmIChleGl0SW5mby5zaWduYWwgIT09IG51bGwpIHtcbiAgICByZXR1cm4gYHdhcyB0ZXJtaW5hdGVkIGJ5IHNpZ25hbCAke2V4aXRJbmZvLnNpZ25hbH1gO1xuICB9XG4gIHJldHVybiBgZXhpdGVkIHByZW1hdHVyZWx5IHdpdGggY29kZSAke2V4aXRJbmZvLmNvZGUgPT09IG51bGwgPyAnKG51bGwpJyA6IFN0cmluZyhleGl0SW5mby5jb2RlKX1gO1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIkFBcUVPLFNBQVMsd0JBQXdCLFFBQStDO0FBQ3JGLFFBQU0sRUFBRSxVQUFVLFFBQVEsYUFBYSxRQUFRLElBQUk7QUFFbkQsUUFBTSxTQUFTLGNBQWMsUUFBUTtBQUNyQyxRQUFNLGdCQUFnQixPQUFPLEtBQUs7QUFDbEMsUUFBTSxVQUFVLGNBQWMsU0FBUyxJQUNuQztBQUFBO0FBQUEsRUFBTyxXQUFXO0FBQUEsRUFBYSxhQUFhLEtBQzVDO0FBQ0osU0FBTyxHQUFHLE9BQU8sSUFBSSxNQUFNLG1CQUFtQixPQUFPO0FBQ3ZEO0FBUUEsU0FBUyxjQUFjLFVBQW1DO0FBQ3hELE1BQUksU0FBUyxlQUFlLFFBQVc7QUFDckMsV0FBTyxvQkFBb0IsU0FBUyxVQUFVO0FBQUEsRUFDaEQ7QUFDQSxNQUFJLFNBQVMsV0FBVyxNQUFNO0FBQzVCLFdBQU8sNEJBQTRCLFNBQVMsTUFBTTtBQUFBLEVBQ3BEO0FBQ0EsU0FBTyxnQ0FBZ0MsU0FBUyxTQUFTLE9BQU8sV0FBVyxPQUFPLFNBQVMsSUFBSSxDQUFDO0FBQ2xHOyIsCiAgIm5hbWVzIjogW10KfQo=
28
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3Byb2Nlc3MtZXhpdC1tZXNzYWdlLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBmaWxlXG4gKlxuICogUHVyZSBidWlsZGVycyBmb3IgdGhlIGRpYWdub3N0aWMgbWVzc2FnZSBkZXNjcmliaW5nIGFuIGF1dG8tc3RhcnRlZCBjaGlsZFxuICogcHJvY2VzcyAodGhlIEFuZHJvaWQgZW11bGF0b3Igb3IgdGhlIEFwcGl1bSBzZXJ2ZXIpIHRoYXQgZmFpbGVkIGR1cmluZ1xuICogc3RhcnR1cCwgYXBwZW5kaW5nIHRoZSBjYXB0dXJlZCBvdXRwdXQgdGFpbCB3aGVuIGF2YWlsYWJsZS5cbiAqXG4gKiBBIHN0YXJ0dXAgZmFpbHMgdHdvIHdheXMgXHUyMDE0IHRoZSBwcm9jZXNzICoqZGllcyoqLCBvciBpdCAqKmhhbmdzKiogcGFzdCBhXG4gKiBidWRnZXQgXHUyMDE0IGFuZCB0aGUgY2FwdHVyZWQgdGFpbCBpcyBlcXVhbGx5IHRoZSBleHBsYW5hdGlvbiBpbiBib3RoLiBTbyB0aGVcbiAqIHRhaWwtYXBwZW5kaW5nIGhhbGYgaXMgaXRzIG93biBleHBvcnQsIHVzZWQgYnkgdGhlIHRpbWVvdXQgdGhyb3dzIHRoYXQgb25jZVxuICogcmVwb3J0ZWQgb25seSB0aGUgYnVkZ2V0IHRoZXkgYmxldy5cbiAqXG4gKiBLZXB0IHNlcGFyYXRlIGZyb20gdGhlIGludGVncmF0aW9uLW9ubHkgYHRyYW5zcG9ydC1mYWN0b3J5YCAoZXhjbHVkZWQgZnJvbVxuICogdW5pdCB0ZXN0cykgc28gdGhlIG1lc3NhZ2UgZm9ybWF0dGluZyBzdGF5cyB1bml0LXRlc3RhYmxlIFx1MjAxNCB0aGUgbGF1bmNoZXJzXG4gKiB0aGVtc2VsdmVzIHNwYXduIHJlYWwgcHJvY2Vzc2VzLlxuICovXG5cbi8qKlxuICogUGFyYW1ldGVycyBmb3Ige0BsaW5rIGFwcGVuZFByb2Nlc3NPdXRwdXRUYWlsfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBcHBlbmRQcm9jZXNzT3V0cHV0VGFpbFBhcmFtcyB7XG4gIC8qKlxuICBUaGUgY2FwdHVyZWQgc3Rkb3V0K3N0ZGVyciB0YWlsIChlbXB0eSB3aGVuIG5vbmUgd2FzIGNhcHR1cmVkKS5cbiAgICovXG4gIHJlYWRvbmx5IG91dHB1dDogc3RyaW5nO1xuXG4gIC8qKlxuICBMYWJlbCBmb3IgdGhlIGNhcHR1cmVkIG91dHB1dCBzZWN0aW9uIChlLmcuIGBcIkVtdWxhdG9yIG91dHB1dFwiYCkuXG4gICAqL1xuICByZWFkb25seSBvdXRwdXRMYWJlbDogc3RyaW5nO1xufVxuXG4vKipcbiAqIFBhcmFtZXRlcnMgZm9yIHtAbGluayBidWlsZFByb2Nlc3NFeGl0TWVzc2FnZX0uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQnVpbGRQcm9jZXNzRXhpdE1lc3NhZ2VQYXJhbXMge1xuICAvKipcbiAgVGhlIHByb2Nlc3MncyBleGl0IC8gc3Bhd24tZmFpbHVyZSBkZXRhaWxzLlxuICAgKi9cbiAgcmVhZG9ubHkgZXhpdEluZm86IFByb2Nlc3NFeGl0SW5mbztcblxuICAvKipcbiAgVGhlIGNhcHR1cmVkIHN0ZG91dCtzdGRlcnIgdGFpbCAoZW1wdHkgd2hlbiBub25lIHdhcyBjYXB0dXJlZCkuXG4gICAqL1xuICByZWFkb25seSBvdXRwdXQ6IHN0cmluZztcblxuICAvKipcbiAgTGFiZWwgZm9yIHRoZSBjYXB0dXJlZCBvdXRwdXQgc2VjdGlvbiAoZS5nLiBgXCJFbXVsYXRvciBvdXRwdXRcImApLlxuICAgKi9cbiAgcmVhZG9ubHkgb3V0cHV0TGFiZWw6IHN0cmluZztcblxuICAvKipcbiAgSHVtYW4tcmVhZGFibGUgc3ViamVjdCBvZiB0aGUgcHJvY2VzcyAoZS5nLiBgXCJBbmRyb2lkIGVtdWxhdG9yXCJgKS5cbiAgICovXG4gIHJlYWRvbmx5IHN1YmplY3Q6IHN0cmluZztcbn1cblxuLyoqXG4gKiBEZXRhaWxzIG9mIGEgc3Bhd25lZCBjaGlsZCBwcm9jZXNzIHRoYXQgaGFzIGV4aXRlZCBvciBmYWlsZWQgdG8gc3Bhd24uXG4gKlxuICogQSBub3JtYWwgZXhpdCBzZXRzIGBjb2RlYC9gc2lnbmFsYCAoZXhhY3RseSBvbmUgaXMgbm9uLWBudWxsYCk7IGEgc3Bhd25cbiAqIGZhaWx1cmUgKGUuZy4gYEVOT0VOVGAgZm9yIGEgbWlzc2luZyBiaW5hcnkpIGxlYXZlcyBib3RoIGBudWxsYCBhbmQgc2V0c1xuICogYHNwYXduRXJyb3JgIHRvIHRoZSBmYWlsdXJlIG1lc3NhZ2UuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUHJvY2Vzc0V4aXRJbmZvIHtcbiAgLyoqXG4gIEV4aXQgY29kZSwgb3IgYG51bGxgIHdoZW4gdGVybWluYXRlZCBieSBhIHNpZ25hbCBvciB3aGVuIGl0IGZhaWxlZCB0byBzcGF3bi5cbiAgICovXG4gIHJlYWRvbmx5IGNvZGU6IG51bGwgfCBudW1iZXI7XG5cbiAgLyoqXG4gIFRlcm1pbmF0aW5nIHNpZ25hbCwgb3IgYG51bGxgIHdoZW4gaXQgZXhpdGVkIG5vcm1hbGx5IG9yIGZhaWxlZCB0byBzcGF3bi5cbiAgICovXG4gIHJlYWRvbmx5IHNpZ25hbDogTm9kZUpTLlNpZ25hbHMgfCBudWxsO1xuXG4gIC8qKlxuICBUaGUgc3Bhd24tZmFpbHVyZSBtZXNzYWdlIHdoZW4gdGhlIHByb2Nlc3MgbmV2ZXIgc3RhcnRlZCAoZS5nLiBgRU5PRU5UYCksIG90aGVyd2lzZSBhYnNlbnQuXG4gICAqL1xuICByZWFkb25seSBzcGF3bkVycm9yPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIEFwcGVuZHMgYSBwcm9jZXNzJ3MgY2FwdHVyZWQgb3V0cHV0IHRhaWwgdG8gYSBtZXNzYWdlLCB3aGVuIHRoZXJlIGlzIG9uZS5cbiAqXG4gKiBTcGxpdCBvdXQgb2Yge0BsaW5rIGJ1aWxkUHJvY2Vzc0V4aXRNZXNzYWdlfSBzbyB0aGUgKip0aW1lb3V0KiogZmFpbHVyZXMgY2FuXG4gKiBjYXJyeSB0aGUgdGFpbCB0b28uIEEgcHJvY2VzcyB0aGF0IGRpZXMgZ2V0cyBpdHMgb3V0cHV0IGF0dGFjaGVkOyBvbmUgdGhhdFxuICogaGFuZ3MgdXNlZCB0byBnZXQgYE5vIG5ldyBlbXVsYXRvciBkZXZpY2UgYXBwZWFyZWQgd2l0aGluIDMwMDAwMG1zLmAgYW5kXG4gKiBub3RoaW5nIGVsc2UgXHUyMDE0IGV2ZW4gdGhvdWdoIHRoZSBsaW5lIHRoYXQgZXhwbGFpbnMgaXQgKGBGQVRBTCB8IFJ1bm5pbmdcbiAqIG11bHRpcGxlIGVtdWxhdG9ycyB3aXRoIHRoZSBzYW1lIEFWRCBpcyBhbiBleHBlcmltZW50YWwgZmVhdHVyZWApIGhhZCBhbHJlYWR5XG4gKiBiZWVuIGNhcHR1cmVkLiBUaGUgZW11bGF0b3Igd3JpdGluZyBpdHMgb3duIGRpYWdub3NpcyBpcyB3b3J0aCBub3RoaW5nIGlmIHRoZVxuICogaGFybmVzcyByZWFkcyBpdCBvbiBvbmx5IG9uZSBvZiB0aGUgdHdvIHdheXMgYSBzdGFydHVwIGNhbiBmYWlsLlxuICpcbiAqIEBwYXJhbSBtZXNzYWdlIC0gVGhlIGZhaWx1cmUgbWVzc2FnZSB0byBleHRlbmQuXG4gKiBAcGFyYW0gcGFyYW1zIC0gVGhlIGNhcHR1cmVkIHRhaWwgYW5kIGl0cyBsYWJlbC5cbiAqIEByZXR1cm5zIFRoZSBtZXNzYWdlLCB3aXRoIHRoZSB0YWlsIGFwcGVuZGVkIHdoZW4gbm9uLWVtcHR5LlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXBwZW5kUHJvY2Vzc091dHB1dFRhaWwobWVzc2FnZTogc3RyaW5nLCBwYXJhbXM6IEFwcGVuZFByb2Nlc3NPdXRwdXRUYWlsUGFyYW1zKTogc3RyaW5nIHtcbiAgY29uc3QgdHJpbW1lZE91dHB1dCA9IHBhcmFtcy5vdXRwdXQudHJpbSgpO1xuICBpZiAodHJpbW1lZE91dHB1dC5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfVxuXG4gIHJldHVybiBgJHttZXNzYWdlfVxcblxcbiR7cGFyYW1zLm91dHB1dExhYmVsfSAodGFpbCk6XFxuJHt0cmltbWVkT3V0cHV0fWA7XG59XG5cbi8qKlxuICogQnVpbGRzIGEgZGVzY3JpcHRpdmUgZXJyb3IgbWVzc2FnZSBmb3IgYW4gYXV0by1zdGFydGVkIGNoaWxkIHByb2Nlc3MgdGhhdFxuICogZXhpdGVkIChvciBmYWlsZWQgdG8gc3Bhd24pIGR1cmluZyBzdGFydHVwLCBhcHBlbmRpbmcgdGhlIGNhcHR1cmVkIG91dHB1dFxuICogdGFpbCB3aGVuIGF2YWlsYWJsZS5cbiAqXG4gKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHN1YmplY3QsIGV4aXQgZGV0YWlscywgYW5kIGNhcHR1cmVkIG91dHB1dC5cbiAqIEByZXR1cm5zIEEgaHVtYW4tcmVhZGFibGUgZXJyb3IgbWVzc2FnZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkUHJvY2Vzc0V4aXRNZXNzYWdlKHBhcmFtczogQnVpbGRQcm9jZXNzRXhpdE1lc3NhZ2VQYXJhbXMpOiBzdHJpbmcge1xuICBjb25zdCB7IGV4aXRJbmZvLCBvdXRwdXQsIG91dHB1dExhYmVsLCBzdWJqZWN0IH0gPSBwYXJhbXM7XG5cbiAgcmV0dXJuIGFwcGVuZFByb2Nlc3NPdXRwdXRUYWlsKGAke3N1YmplY3R9ICR7cmVzb2x2ZVJlYXNvbihleGl0SW5mbyl9IGR1cmluZyBzdGFydHVwLmAsIHsgb3V0cHV0LCBvdXRwdXRMYWJlbCB9KTtcbn1cblxuLyoqXG4gKiBEZXNjcmliZXMgd2h5IHRoZSBwcm9jZXNzIGlzIG5vIGxvbmdlciBydW5uaW5nLlxuICpcbiAqIEBwYXJhbSBleGl0SW5mbyAtIFRoZSBleGl0IC8gc3Bhd24tZmFpbHVyZSBkZXRhaWxzLlxuICogQHJldHVybnMgVGhlIHJlYXNvbiBjbGF1c2UuXG4gKi9cbmZ1bmN0aW9uIHJlc29sdmVSZWFzb24oZXhpdEluZm86IFByb2Nlc3NFeGl0SW5mbyk6IHN0cmluZyB7XG4gIGlmIChleGl0SW5mby5zcGF3bkVycm9yICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gYGZhaWxlZCB0byBzdGFydCAoJHtleGl0SW5mby5zcGF3bkVycm9yfSlgO1xuICB9XG4gIGlmIChleGl0SW5mby5zaWduYWwgIT09IG51bGwpIHtcbiAgICByZXR1cm4gYHdhcyB0ZXJtaW5hdGVkIGJ5IHNpZ25hbCAke2V4aXRJbmZvLnNpZ25hbH1gO1xuICB9XG4gIHJldHVybiBgZXhpdGVkIHByZW1hdHVyZWx5IHdpdGggY29kZSAke2V4aXRJbmZvLmNvZGUgPT09IG51bGwgPyAnKG51bGwpJyA6IFN0cmluZyhleGl0SW5mby5jb2RlKX1gO1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIkFBZ0dPLFNBQVMsd0JBQXdCLFNBQWlCLFFBQStDO0FBQ3RHLFFBQU0sZ0JBQWdCLE9BQU8sT0FBTyxLQUFLO0FBQ3pDLE1BQUksY0FBYyxXQUFXLEdBQUc7QUFDOUIsV0FBTztBQUFBLEVBQ1Q7QUFFQSxTQUFPLEdBQUcsT0FBTztBQUFBO0FBQUEsRUFBTyxPQUFPLFdBQVc7QUFBQSxFQUFhLGFBQWE7QUFDdEU7QUFVTyxTQUFTLHdCQUF3QixRQUErQztBQUNyRixRQUFNLEVBQUUsVUFBVSxRQUFRLGFBQWEsUUFBUSxJQUFJO0FBRW5ELFNBQU8sd0JBQXdCLEdBQUcsT0FBTyxJQUFJLGNBQWMsUUFBUSxDQUFDLG9CQUFvQixFQUFFLFFBQVEsWUFBWSxDQUFDO0FBQ2pIO0FBUUEsU0FBUyxjQUFjLFVBQW1DO0FBQ3hELE1BQUksU0FBUyxlQUFlLFFBQVc7QUFDckMsV0FBTyxvQkFBb0IsU0FBUyxVQUFVO0FBQUEsRUFDaEQ7QUFDQSxNQUFJLFNBQVMsV0FBVyxNQUFNO0FBQzVCLFdBQU8sNEJBQTRCLFNBQVMsTUFBTTtBQUFBLEVBQ3BEO0FBQ0EsU0FBTyxnQ0FBZ0MsU0FBUyxTQUFTLE9BQU8sV0FBVyxPQUFPLFNBQVMsSUFBSSxDQUFDO0FBQ2xHOyIsCiAgIm5hbWVzIjogW10KfQo=
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @file
3
+ *
4
+ * Cheap, synchronous "is this PID still running?" probe.
5
+ *
6
+ * Signal `0` performs the permission and existence checks without delivering a
7
+ * signal, on Windows as well as POSIX, so it costs nothing at teardown-poll
8
+ * frequency. `EPERM` means the process exists but is owned by another user —
9
+ * still alive, and the distinction matters: reading it as dead is how a
10
+ * teardown convinces itself a process it could not touch is gone.
11
+ */
12
+ /**
13
+ * Checks whether a process is still running.
14
+ *
15
+ * @param pid - The PID to probe.
16
+ * @returns `true` when the process exists.
17
+ */
18
+ export declare function checkIsProcessAlive(pid: number): boolean;
@@ -0,0 +1,17 @@
1
+ import process from "node:process";
2
+ const PROCESS_EXISTENCE_PROBE_SIGNAL = 0;
3
+ function checkIsProcessAlive(pid) {
4
+ try {
5
+ process.kill(pid, PROCESS_EXISTENCE_PROBE_SIGNAL);
6
+ return true;
7
+ } catch (error) {
8
+ return getErrorCode(error) === "EPERM";
9
+ }
10
+ }
11
+ function getErrorCode(error) {
12
+ return typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0;
13
+ }
14
+ export {
15
+ checkIsProcessAlive
16
+ };
17
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3Byb2Nlc3MtbGl2ZW5lc3MudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qKlxuICogQGZpbGVcbiAqXG4gKiBDaGVhcCwgc3luY2hyb25vdXMgXCJpcyB0aGlzIFBJRCBzdGlsbCBydW5uaW5nP1wiIHByb2JlLlxuICpcbiAqIFNpZ25hbCBgMGAgcGVyZm9ybXMgdGhlIHBlcm1pc3Npb24gYW5kIGV4aXN0ZW5jZSBjaGVja3Mgd2l0aG91dCBkZWxpdmVyaW5nIGFcbiAqIHNpZ25hbCwgb24gV2luZG93cyBhcyB3ZWxsIGFzIFBPU0lYLCBzbyBpdCBjb3N0cyBub3RoaW5nIGF0IHRlYXJkb3duLXBvbGxcbiAqIGZyZXF1ZW5jeS4gYEVQRVJNYCBtZWFucyB0aGUgcHJvY2VzcyBleGlzdHMgYnV0IGlzIG93bmVkIGJ5IGFub3RoZXIgdXNlciBcdTIwMTRcbiAqIHN0aWxsIGFsaXZlLCBhbmQgdGhlIGRpc3RpbmN0aW9uIG1hdHRlcnM6IHJlYWRpbmcgaXQgYXMgZGVhZCBpcyBob3cgYVxuICogdGVhcmRvd24gY29udmluY2VzIGl0c2VsZiBhIHByb2Nlc3MgaXQgY291bGQgbm90IHRvdWNoIGlzIGdvbmUuXG4gKi9cblxuaW1wb3J0IHByb2Nlc3MgZnJvbSAnbm9kZTpwcm9jZXNzJztcblxuY29uc3QgUFJPQ0VTU19FWElTVEVOQ0VfUFJPQkVfU0lHTkFMID0gMDtcblxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciBhIHByb2Nlc3MgaXMgc3RpbGwgcnVubmluZy5cbiAqXG4gKiBAcGFyYW0gcGlkIC0gVGhlIFBJRCB0byBwcm9iZS5cbiAqIEByZXR1cm5zIGB0cnVlYCB3aGVuIHRoZSBwcm9jZXNzIGV4aXN0cy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNoZWNrSXNQcm9jZXNzQWxpdmUocGlkOiBudW1iZXIpOiBib29sZWFuIHtcbiAgdHJ5IHtcbiAgICBwcm9jZXNzLmtpbGwocGlkLCBQUk9DRVNTX0VYSVNURU5DRV9QUk9CRV9TSUdOQUwpO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgIHJldHVybiBnZXRFcnJvckNvZGUoZXJyb3IpID09PSAnRVBFUk0nO1xuICB9XG59XG5cbmZ1bmN0aW9uIGdldEVycm9yQ29kZShlcnJvcjogdW5rbm93bik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiB0eXBlb2YgZXJyb3IgPT09ICdvYmplY3QnICYmIGVycm9yICE9PSBudWxsICYmICdjb2RlJyBpbiBlcnJvciA/IFN0cmluZyhlcnJvci5jb2RlKSA6IHVuZGVmaW5lZDtcbn1cbiJdLAogICJtYXBwaW5ncyI6ICJBQVlBLE9BQU8sYUFBYTtBQUVwQixNQUFNLGlDQUFpQztBQVFoQyxTQUFTLG9CQUFvQixLQUFzQjtBQUN4RCxNQUFJO0FBQ0YsWUFBUSxLQUFLLEtBQUssOEJBQThCO0FBQ2hELFdBQU87QUFBQSxFQUNULFNBQVMsT0FBZ0I7QUFDdkIsV0FBTyxhQUFhLEtBQUssTUFBTTtBQUFBLEVBQ2pDO0FBQ0Y7QUFFQSxTQUFTLGFBQWEsT0FBb0M7QUFDeEQsU0FBTyxPQUFPLFVBQVUsWUFBWSxVQUFVLFFBQVEsVUFBVSxRQUFRLE9BQU8sTUFBTSxJQUFJLElBQUk7QUFDL0Y7IiwKICAibmFtZXMiOiBbXQp9Cg==