obsidian-integration-testing 10.4.0 → 12.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/README.md +1 -1
  2. package/dist/lib/cjs/appium-server-marker.cjs +115 -0
  3. package/dist/lib/cjs/appium-server-marker.d.cts +81 -0
  4. package/dist/lib/cjs/cli.cjs +104 -19
  5. package/dist/lib/cjs/cli.d.cts +16 -8
  6. package/dist/lib/cjs/community-plugin-registry.cjs +52 -0
  7. package/dist/lib/cjs/community-plugin-registry.d.cts +116 -0
  8. package/dist/lib/cjs/context-provider.cjs +12 -1
  9. package/dist/lib/cjs/context-provider.d.cts +26 -3
  10. package/dist/lib/cjs/demo-vault-bootstrap.cjs +148 -0
  11. package/dist/lib/cjs/demo-vault-bootstrap.d.cts +113 -0
  12. package/dist/lib/cjs/demo-vault-populate.cjs +36 -9
  13. package/dist/lib/cjs/demo-vault-populate.d.cts +70 -0
  14. package/dist/lib/cjs/eval-in-obsidian.cjs +1 -1
  15. package/dist/lib/cjs/eval-in-obsidian.d.cts +97 -15
  16. package/dist/lib/cjs/index.cjs +16 -1
  17. package/dist/lib/cjs/index.d.cts +15 -8
  18. package/dist/lib/cjs/installer-asset.cjs +1 -1
  19. package/dist/lib/cjs/installer-asset.d.cts +1 -1
  20. package/dist/lib/cjs/integration-setup-failed-error.cjs +62 -0
  21. package/dist/lib/cjs/integration-setup-failed-error.d.cts +66 -0
  22. package/dist/lib/cjs/jest/global-setup.cjs +2 -2
  23. package/dist/lib/cjs/jest/global-setup.d.cts +5 -1
  24. package/dist/lib/cjs/kill-process-tree.cjs +18 -7
  25. package/dist/lib/cjs/kill-process-tree.d.cts +10 -2
  26. package/dist/lib/cjs/library.cjs +1 -1
  27. package/dist/lib/cjs/mobile-input.cjs +161 -0
  28. package/dist/lib/cjs/mobile-input.d.cts +160 -0
  29. package/dist/lib/cjs/namespace-bootstrap.cjs +136 -10
  30. package/dist/lib/cjs/obsidian-installer.cjs +1 -1
  31. package/dist/lib/cjs/obsidian-metadata.cjs +1257 -348
  32. package/dist/lib/cjs/obsidian-metadata.d.cts +74 -12
  33. package/dist/lib/cjs/obsidian-version-switch.cjs +3 -3
  34. package/dist/lib/cjs/open-obsidian-settings-tab.cjs +51 -0
  35. package/dist/lib/cjs/open-obsidian-settings-tab.d.cts +49 -0
  36. package/dist/lib/cjs/release-catalog.cjs +73 -0
  37. package/dist/lib/cjs/release-catalog.d.cts +125 -0
  38. package/dist/lib/cjs/transport-appium.cjs +122 -1
  39. package/dist/lib/cjs/transport-appium.d.cts +51 -0
  40. package/dist/lib/cjs/transport-desktop-cdp.cjs +7 -1
  41. package/dist/lib/cjs/transport-desktop-cdp.d.cts +2 -2
  42. package/dist/lib/cjs/transport-factory.cjs +237 -32
  43. package/dist/lib/cjs/transport-factory.d.cts +10 -1
  44. package/dist/lib/cjs/vitest/global-setup.cjs +13 -7
  45. package/dist/lib/cjs/vitest/global-setup.d.cts +5 -1
  46. package/dist/lib/cjs/vitest/setup.cjs +2 -1
  47. package/dist/lib/cjs/vitest/setup.d.cts +5 -0
  48. package/dist/lib/cjs/vitest/typings.d.cts +6 -4
  49. package/dist/lib/cjs/webview-cdp.cjs +264 -0
  50. package/dist/lib/cjs/webview-cdp.d.cts +152 -0
  51. package/dist/lib/cjs/wedged-appium-server.cjs +113 -0
  52. package/dist/lib/cjs/wedged-appium-server.d.cts +187 -0
  53. package/dist/lib/esm/appium-server-marker.d.mts +81 -0
  54. package/dist/lib/esm/appium-server-marker.mjs +83 -0
  55. package/dist/lib/esm/cli.d.mts +16 -8
  56. package/dist/lib/esm/cli.mjs +110 -19
  57. package/dist/lib/esm/community-plugin-registry.d.mts +116 -0
  58. package/dist/lib/esm/community-plugin-registry.mjs +23 -0
  59. package/dist/lib/esm/context-provider.d.mts +26 -3
  60. package/dist/lib/esm/context-provider.mjs +10 -1
  61. package/dist/lib/esm/demo-vault-bootstrap.d.mts +113 -0
  62. package/dist/lib/esm/demo-vault-bootstrap.mjs +127 -0
  63. package/dist/lib/esm/demo-vault-populate.d.mts +70 -0
  64. package/dist/lib/esm/demo-vault-populate.mjs +33 -8
  65. package/dist/lib/esm/eval-in-obsidian.d.mts +97 -15
  66. package/dist/lib/esm/eval-in-obsidian.mjs +1 -1
  67. package/dist/lib/esm/index.d.mts +15 -8
  68. package/dist/lib/esm/index.mjs +18 -2
  69. package/dist/lib/esm/installer-asset.d.mts +1 -1
  70. package/dist/lib/esm/installer-asset.mjs +1 -1
  71. package/dist/lib/esm/integration-setup-failed-error.d.mts +66 -0
  72. package/dist/lib/esm/integration-setup-failed-error.mjs +38 -0
  73. package/dist/lib/esm/jest/global-setup.d.mts +5 -1
  74. package/dist/lib/esm/jest/global-setup.mjs +2 -2
  75. package/dist/lib/esm/kill-process-tree.d.mts +10 -2
  76. package/dist/lib/esm/kill-process-tree.mjs +16 -6
  77. package/dist/lib/esm/library.mjs +1 -1
  78. package/dist/lib/esm/mobile-input.d.mts +160 -0
  79. package/dist/lib/esm/mobile-input.mjs +132 -0
  80. package/dist/lib/esm/namespace-bootstrap.mjs +139 -10
  81. package/dist/lib/esm/obsidian-installer.mjs +1 -1
  82. package/dist/lib/esm/obsidian-metadata.d.mts +74 -12
  83. package/dist/lib/esm/obsidian-metadata.mjs +1257 -348
  84. package/dist/lib/esm/obsidian-version-switch.mjs +3 -3
  85. package/dist/lib/esm/open-obsidian-settings-tab.d.mts +49 -0
  86. package/dist/lib/esm/open-obsidian-settings-tab.mjs +27 -0
  87. package/dist/lib/esm/release-catalog.d.mts +125 -0
  88. package/dist/lib/esm/release-catalog.mjs +46 -0
  89. package/dist/lib/esm/transport-appium.d.mts +51 -0
  90. package/dist/lib/esm/transport-appium.mjs +126 -1
  91. package/dist/lib/esm/transport-desktop-cdp.d.mts +2 -2
  92. package/dist/lib/esm/transport-desktop-cdp.mjs +7 -1
  93. package/dist/lib/esm/transport-factory.d.mts +10 -1
  94. package/dist/lib/esm/transport-factory.mjs +249 -35
  95. package/dist/lib/esm/vitest/global-setup.d.mts +5 -1
  96. package/dist/lib/esm/vitest/global-setup.mjs +14 -7
  97. package/dist/lib/esm/vitest/setup.d.mts +5 -0
  98. package/dist/lib/esm/vitest/setup.mjs +3 -1
  99. package/dist/lib/esm/vitest/typings.d.mts +6 -4
  100. package/dist/lib/esm/webview-cdp.d.mts +152 -0
  101. package/dist/lib/esm/webview-cdp.mjs +236 -0
  102. package/dist/lib/esm/wedged-appium-server.d.mts +187 -0
  103. package/dist/lib/esm/wedged-appium-server.mjs +86 -0
  104. package/package.json +13 -12
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var wedged_appium_server_exports = {};
20
+ __export(wedged_appium_server_exports, {
21
+ buildWedgedAppiumServerMessage: () => buildWedgedAppiumServerMessage,
22
+ checkIsAppiumDeviceNotFoundError: () => checkIsAppiumDeviceNotFoundError,
23
+ checkIsAppiumStatusReady: () => checkIsAppiumStatusReady,
24
+ resolveWedgedAppiumServerRemedy: () => resolveWedgedAppiumServerRemedy
25
+ });
26
+ module.exports = __toCommonJS(wedged_appium_server_exports);
27
+ var import_error_to_string = require("./error-to-string.cjs");
28
+ const DEVICE_NOT_FOUND_MESSAGE_FRAGMENT = "Could not find a connected Android device";
29
+ const MILLISECONDS_PER_SECOND = 1e3;
30
+ const SECONDS_PER_MINUTE = 60;
31
+ const MILLISECONDS_PER_MINUTE = MILLISECONDS_PER_SECOND * SECONDS_PER_MINUTE;
32
+ function buildWedgedAppiumServerMessage(params) {
33
+ const lines = [
34
+ `The Appium server at ${params.appiumOrigin} cannot see Android device ${params.deviceId}, although this host's adb can.`,
35
+ "The server is stale \u2014 its adb connection is wedged \u2014 not the device, so `adb devices` will list the device and mislead you.",
36
+ resolveRemedyAdvice(params)
37
+ ];
38
+ const provenance = describeServer(params);
39
+ if (provenance) {
40
+ lines.push(provenance);
41
+ }
42
+ return lines.join("\n");
43
+ }
44
+ function checkIsAppiumDeviceNotFoundError(error) {
45
+ return (0, import_error_to_string.errorToString)(error).includes(DEVICE_NOT_FOUND_MESSAGE_FRAGMENT);
46
+ }
47
+ function checkIsAppiumStatusReady(statusBody) {
48
+ let parsed;
49
+ try {
50
+ parsed = JSON.parse(statusBody);
51
+ } catch {
52
+ return true;
53
+ }
54
+ return readReadyFlag(parsed) !== false;
55
+ }
56
+ function resolveWedgedAppiumServerRemedy(params) {
57
+ if (!checkIsAppiumDeviceNotFoundError(params.error)) {
58
+ return { reason: "other-error", remedy: "not-wedged" };
59
+ }
60
+ if (!params.connectedDeviceIds.includes(params.deviceId)) {
61
+ return { reason: "device-absent", remedy: "not-wedged" };
62
+ }
63
+ if (!params.isAdoptedServer) {
64
+ return { reason: "freshly-started", remedy: "report" };
65
+ }
66
+ if (!params.isAutoStartAllowed) {
67
+ return { reason: "auto-start-disabled", remedy: "report" };
68
+ }
69
+ if (!params.isHarnessOwnedServer) {
70
+ return { reason: "foreign-server", remedy: "report" };
71
+ }
72
+ return { reason: "harness-owned", remedy: "restart" };
73
+ }
74
+ function describeServer(params) {
75
+ if (params.serverPid === void 0) {
76
+ return "";
77
+ }
78
+ const age = params.serverAgeInMilliseconds === void 0 ? "" : `, running for ${formatAge(params.serverAgeInMilliseconds)}`;
79
+ return `The server was started by an earlier obsidian-integration-testing run (pid ${String(params.serverPid)}${age}).`;
80
+ }
81
+ function formatAge(ageInMilliseconds) {
82
+ if (ageInMilliseconds < MILLISECONDS_PER_MINUTE) {
83
+ return `${String(Math.round(ageInMilliseconds / MILLISECONDS_PER_SECOND))}s`;
84
+ }
85
+ return `${String(Math.round(ageInMilliseconds / MILLISECONDS_PER_MINUTE))}min`;
86
+ }
87
+ function readReadyFlag(parsed) {
88
+ if (typeof parsed !== "object" || parsed === null) {
89
+ return void 0;
90
+ }
91
+ const record = parsed;
92
+ const value = record["value"];
93
+ const nested = typeof value === "object" && value !== null ? value["ready"] : void 0;
94
+ const ready = nested ?? record["ready"];
95
+ return typeof ready === "boolean" ? ready : void 0;
96
+ }
97
+ function resolveRemedyAdvice(params) {
98
+ const advice = {
99
+ "auto-start-disabled": `Appium auto-start is disabled (\`shouldAutoStartAppium: false\`), so this server is yours to manage: kill it and start a fresh one on ${params.appiumOrigin}, then re-run.`,
100
+ "foreign-server": `This server was not started by obsidian-integration-testing, so it was left running: kill it and start a fresh one on ${params.appiumOrigin}, then re-run.`,
101
+ "freshly-started": "This server was started by this run, so restarting it would change nothing: check that adb and the emulator agree (`adb kill-server && adb devices`), then re-run.",
102
+ "restart-did-not-help": `Restarting the server on ${params.appiumOrigin} did not help \u2014 a fresh one still could not serve this run, so the wedge is not the server alone: check adb itself (\`adb kill-server && adb devices\`) and that nothing else holds the port, then re-run.`
103
+ };
104
+ return advice[params.reason];
105
+ }
106
+ // Annotate the CommonJS export names for ESM import in node:
107
+ 0 && (module.exports = {
108
+ buildWedgedAppiumServerMessage,
109
+ checkIsAppiumDeviceNotFoundError,
110
+ checkIsAppiumStatusReady,
111
+ resolveWedgedAppiumServerRemedy
112
+ });
113
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3dlZGdlZC1hcHBpdW0tc2VydmVyLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBmaWxlXG4gKlxuICogUHVyZSBoZWxwZXJzIGZvciByZWNvZ25pemluZyBhICoqd2VkZ2VkKiogQXBwaXVtIHNlcnZlciBhbmQgZGVjaWRpbmcgd2hhdCB0b1xuICogZG8gYWJvdXQgaXQuIEtlcHQgc2VwYXJhdGUgZnJvbSB0aGUgaW50ZWdyYXRpb24tb25seSBgdHJhbnNwb3J0LWZhY3RvcnlgIHNvXG4gKiB0aGUgY2xhc3NpZmljYXRpb24sIHRoZSByZW1lZHkgZGVjaXNpb24gYW5kIHRoZSBtZXNzYWdlIHN0YXkgdW5pdC10ZXN0YWJsZVxuICogKHRoZSBmYWN0b3J5IGl0c2VsZiBuZWVkcyBhIHJlYWwgZGV2aWNlIGFuZCBpcyBleGNsdWRlZCBmcm9tIHVuaXQgdGVzdHMpLlxuICpcbiAqIEEgd2VkZ2VkIHNlcnZlciBpcyBvbmUgdGhhdCBpcyBzdGlsbCAqKmxpdmUqKiBcdTIwMTQgaXQgbGlzdGVucyBvbiBpdHMgcG9ydCBhbmRcbiAqIGFuc3dlcnMgYC9zdGF0dXNgIHdpdGggYHJlYWR5OiB0cnVlYCBcdTIwMTQgYnV0IGlzIG5vIGxvbmdlciAqKnVzYWJsZSoqOiBpdHNcbiAqIGBhcHBpdW0tYWRiYCBjYW4gbm8gbG9uZ2VyIGVudW1lcmF0ZSBkZXZpY2VzLCBzbyBldmVyeSBzZXNzaW9uIGNyZWF0aW9uIGRpZXNcbiAqIHdpdGggYENvdWxkIG5vdCBmaW5kIGEgY29ubmVjdGVkIEFuZHJvaWQgZGV2aWNlIGluIDxuPm1zYCB3aGlsZSB0aGUgaG9zdCdzIG93blxuICogYGFkYiBkZXZpY2VzYCBsaXN0cyB0aGUgZGV2aWNlIGluc3RhbnRseS4gTGl2ZW5lc3MgaXMgbm90IHJlYWRpbmVzcywgYW5kIHRoZVxuICogZXJyb3IgbmFtZXMgdGhlIHdyb25nIHN1YmplY3Q6IGl0IGJsYW1lcyBhIGRldmljZSB0aGF0IGlzIGRlbW9uc3RyYWJseVxuICogcHJlc2VudCwgd2hpY2ggc2VuZHMgd2hvZXZlciByZWFkcyBpdCB0byBgYWRiIGRldmljZXNgIFx1MjAxNCB0aGUgb25lIGRpYWdub3N0aWNcbiAqIHRoYXQgYWN0aXZlbHkgbWlzbGVhZHMgaGVyZS5cbiAqXG4gKiBUaGUgd2VkZ2UgZGV2ZWxvcHMgb3ZlciB0aW1lIGluIGEgbG9uZy1saXZlZCBzZXJ2ZXIgKG9uZSBhdXRvLXN0YXJ0ZWQgYnkgYW5cbiAqIGVhcmxpZXIgcnVuIGFuZCBsZWZ0IGxpc3RlbmluZyksIHNvIHRoZSBwcmVmbGlnaHQgY2Fubm90IHNlZSBpdCBjb21pbmc6IGl0IGNhblxuICogb25seSBiZSByZWNvZ25pemVkIGZyb20gdGhlIGZhaWxlZCBzZXNzaW9uLCBjcm9zcy1jaGVja2VkIGFnYWluc3QgdGhlIGhvc3Qnc1xuICogYWRiLlxuICovXG5cbmltcG9ydCB7IGVycm9yVG9TdHJpbmcgfSBmcm9tICcuL2Vycm9yLXRvLXN0cmluZy5janMnO1xuXG4vKipcbiAqIFRoZSBmcmFnbWVudCBgYXBwaXVtLWFkYmAgdGhyb3dzIHdoZW4gaXQgY2Fubm90IGVudW1lcmF0ZSBkZXZpY2VzIFx1MjAxNFxuICogYGAgYENvdWxkIG5vdCBmaW5kIGEgY29ubmVjdGVkIEFuZHJvaWQgZGV2aWNlIGluICR7dGltZW91dE1zfW1zYCBgYCBmcm9tIGl0c1xuICogYGdldERldmljZXNXaXRoUmV0cnlgIChgbGliL3Rvb2xzL3N5c3RlbS1jYWxscy50c2ApLiBNYXRjaGVkIGFzIGEgc3Vic3RyaW5nIHNvXG4gKiB0aGUgdGltZW91dCB2YWx1ZSBhbmQgYW55IHdyYXBwaW5nIGJ5IFdlYmRyaXZlcklPIGRvIG5vdCBhZmZlY3QgaXQuXG4gKi9cbmNvbnN0IERFVklDRV9OT1RfRk9VTkRfTUVTU0FHRV9GUkFHTUVOVCA9ICdDb3VsZCBub3QgZmluZCBhIGNvbm5lY3RlZCBBbmRyb2lkIGRldmljZSc7XG5cbmNvbnN0IE1JTExJU0VDT05EU19QRVJfU0VDT05EID0gMTAwMDtcbmNvbnN0IFNFQ09ORFNfUEVSX01JTlVURSA9IDYwO1xuY29uc3QgTUlMTElTRUNPTkRTX1BFUl9NSU5VVEUgPSBNSUxMSVNFQ09ORFNfUEVSX1NFQ09ORCAqIFNFQ09ORFNfUEVSX01JTlVURTtcblxuLyoqXG4gKiBQYXJhbWV0ZXJzIGZvciB7QGxpbmsgYnVpbGRXZWRnZWRBcHBpdW1TZXJ2ZXJNZXNzYWdlfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBCdWlsZFdlZGdlZEFwcGl1bVNlcnZlck1lc3NhZ2VQYXJhbXMge1xuICAvKipcbiAgT3JpZ2luIG9mIHRoZSBBcHBpdW0gc2VydmVyIHRoYXQgY291bGQgbm90IHNlZSB0aGUgZGV2aWNlIChlLmcuIGBodHRwOi8vbG9jYWxob3N0OjQ3MjNgKS5cbiAgICovXG4gIHJlYWRvbmx5IGFwcGl1bU9yaWdpbjogc3RyaW5nO1xuXG4gIC8qKlxuICBUaGUgZGV2aWNlIHRoZSBob3N0J3MgYWRiIGNhbiBzZWUgYnV0IEFwcGl1bSBjYW5ub3QuXG4gICAqL1xuICByZWFkb25seSBkZXZpY2VJZDogc3RyaW5nO1xuXG4gIC8qKlxuICBXaHkgdGhpcyBydW4gaXMgcmVwb3J0aW5nIHJhdGhlciB0aGFuIHJlc3RhcnRpbmcuXG4gICAqL1xuICByZWFkb25seSByZWFzb246IFdlZGdlZEFwcGl1bVNlcnZlclJlcG9ydFJlYXNvbjtcblxuICAvKipcbiAgSG93IGxvbmcgdGhlIHNlcnZlciBoYXMgYmVlbiBydW5uaW5nLCB3aGVuIGtub3duIGZyb20gaXRzIG1hcmtlci5cbiAgICovXG4gIHJlYWRvbmx5IHNlcnZlckFnZUluTWlsbGlzZWNvbmRzPzogbnVtYmVyIHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICBQSUQgb2YgdGhlIHNlcnZlciwgd2hlbiBrbm93biBmcm9tIGl0cyBtYXJrZXIuXG4gICAqL1xuICByZWFkb25seSBzZXJ2ZXJQaWQ/OiBudW1iZXIgfCB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogVGhlIHNlcnZlciBpcyBub3QgdG8gYmxhbWU6IGVpdGhlciB0aGUgZmFpbHVyZSB3YXMgYSBkaWZmZXJlbnQgZXJyb3IsIG9yIHRoZVxuICogaG9zdCdzIGFkYiBjYW5ub3Qgc2VlIHRoZSBkZXZpY2UgZWl0aGVyLiBUaGUgb3JpZ2luYWwgZXJyb3IgaXMgcmV0aHJvd24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTm90V2VkZ2VkVmVyZGljdCB7XG4gIC8qKlxuICBXaGljaCBvZiB0aGUgdHdvIGhvbmVzdC1mYWlsdXJlIGNhc2VzIHRoaXMgaXMuXG4gICAqL1xuICByZWFkb25seSByZWFzb246ICdkZXZpY2UtYWJzZW50JyB8ICdvdGhlci1lcnJvcic7XG5cbiAgLyoqXG4gIERpc2NyaW1pbmFudC5cbiAgICovXG4gIHJlYWRvbmx5IHJlbWVkeTogJ25vdC13ZWRnZWQnO1xufVxuXG4vKipcbiAqIFRoZSBzZXJ2ZXIgaXMgd2VkZ2VkIGJ1dCBtdXN0IG5vdCBiZSB0b3VjaGVkIGJ5IHRoaXMgcnVuLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlcG9ydFNlcnZlclZlcmRpY3Qge1xuICAvKipcbiAgV2h5IHRoaXMgcnVuIGlzIHJlcG9ydGluZyByYXRoZXIgdGhhbiByZXN0YXJ0aW5nLlxuICAgKi9cbiAgcmVhZG9ubHkgcmVhc29uOiBXZWRnZWRBcHBpdW1TZXJ2ZXJSZXBvcnRSZWFzb247XG5cbiAgLyoqXG4gIERpc2NyaW1pbmFudC5cbiAgICovXG4gIHJlYWRvbmx5IHJlbWVkeTogJ3JlcG9ydCc7XG59XG5cbi8qKlxuICogUGFyYW1ldGVycyBmb3Ige0BsaW5rIHJlc29sdmVXZWRnZWRBcHBpdW1TZXJ2ZXJSZW1lZHl9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlc29sdmVXZWRnZWRBcHBpdW1TZXJ2ZXJSZW1lZHlQYXJhbXMge1xuICAvKipcbiAgRGV2aWNlIElEcyB0aGUgKipob3N0J3MqKiBhZGIgY3VycmVudGx5IGxpc3RzICh0aGUgY3Jvc3MtY2hlY2sgdGhhdCBjb252aWN0cyB0aGUgc2VydmVyKS5cbiAgICovXG4gIHJlYWRvbmx5IGNvbm5lY3RlZERldmljZUlkczogcmVhZG9ubHkgc3RyaW5nW107XG5cbiAgLyoqXG4gIFRoZSBkZXZpY2UgdGhlIHNlc3Npb24gd2FzIHJlcXVlc3RlZCBhZ2FpbnN0LlxuICAgKi9cbiAgcmVhZG9ubHkgZGV2aWNlSWQ6IHN0cmluZztcblxuICAvKipcbiAgVGhlIGVycm9yIHRoZSBzZXNzaW9uIGF0dGVtcHQgZmFpbGVkIHdpdGguXG4gICAqL1xuICByZWFkb25seSBlcnJvcjogdW5rbm93bjtcblxuICAvKipcbiAgV2hldGhlciB0aGUgc2VydmVyIHdhcyBhbHJlYWR5IGxpc3RlbmluZyBhbmQgd2FzIGFkb3B0ZWQsIHJhdGhlciB0aGFuIHN0YXJ0ZWQgYnkgdGhpcyBydW4uXG4gICAqL1xuICByZWFkb25seSBpc0Fkb3B0ZWRTZXJ2ZXI6IGJvb2xlYW47XG5cbiAgLyoqXG4gIFdoZXRoZXIgdGhpcyBydW4gbWF5IHN0YXJ0IGFuIEFwcGl1bSBzZXJ2ZXIgKGBzaG91bGRBdXRvU3RhcnRBcHBpdW1gIGlzIG5vdCBgZmFsc2VgKS5cbiAgICovXG4gIHJlYWRvbmx5IGlzQXV0b1N0YXJ0QWxsb3dlZDogYm9vbGVhbjtcblxuICAvKipcbiAgV2hldGhlciB0aGUgYWRvcHRlZCBzZXJ2ZXIncyBtYXJrZXIgcHJvdmVzIGFuIGVhcmxpZXIgcnVuIG9mIHRoaXMgaGFybmVzcyBzdGFydGVkIGl0LlxuICAgKi9cbiAgcmVhZG9ubHkgaXNIYXJuZXNzT3duZWRTZXJ2ZXI6IGJvb2xlYW47XG59XG5cbi8qKlxuICogVGhlIHNlcnZlciBpcyB3ZWRnZWQgYW5kIGFuIGVhcmxpZXIgcnVuIG9mIHRoaXMgaGFybmVzcyBzdGFydGVkIGl0LCBzbyB0aGlzXG4gKiBydW4gbWF5IHJlcGxhY2UgaXQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVzdGFydFNlcnZlclZlcmRpY3Qge1xuICAvKipcbiAgQWx3YXlzIHRoZSBoYXJuZXNzLW93bmVkIGNhc2UuXG4gICAqL1xuICByZWFkb25seSByZWFzb246ICdoYXJuZXNzLW93bmVkJztcblxuICAvKipcbiAgRGlzY3JpbWluYW50LlxuICAgKi9cbiAgcmVhZG9ubHkgcmVtZWR5OiAncmVzdGFydCc7XG59XG5cbi8qKlxuICogVGhlIGNsYXNzaWZpY2F0aW9uIG9mIGEgZmFpbGVkIHNlc3Npb24gYXR0ZW1wdC5cbiAqXG4gKiBgJ2RldmljZS1hYnNlbnQnYCBhbmQgYCdvdGhlci1lcnJvcidgIGFyZSB0aGUgbm90LXdlZGdlZCB2ZXJkaWN0czogdGhlXG4gKiBvcmlnaW5hbCBlcnJvciB3YXMgaG9uZXN0IGFuZCBpcyByZXRocm93biB1bnRvdWNoZWQuXG4gKi9cbmV4cG9ydCB0eXBlIFdlZGdlZEFwcGl1bVNlcnZlclJlYXNvbiA9ICdkZXZpY2UtYWJzZW50JyB8ICdoYXJuZXNzLW93bmVkJyB8ICdvdGhlci1lcnJvcicgfCBXZWRnZWRBcHBpdW1TZXJ2ZXJSZXBvcnRSZWFzb247XG5cbi8qKlxuICogV2hhdCB0aGUgZmFjdG9yeSBzaG91bGQgZG8gd2l0aCBhIGZhaWxlZCBzZXNzaW9uIGF0dGVtcHQuXG4gKi9cbmV4cG9ydCB0eXBlIFdlZGdlZEFwcGl1bVNlcnZlclJlbWVkeSA9ICdub3Qtd2VkZ2VkJyB8ICdyZXBvcnQnIHwgJ3Jlc3RhcnQnO1xuXG4vKipcbiAqIFdoeSBhIHdlZGdlZCBzZXJ2ZXIgaXMgb25seSByZXBvcnRlZCByYXRoZXIgdGhhbiByZXN0YXJ0ZWQuIEVhY2ggbWFwcyB0byBpdHNcbiAqIG93biByZW1lZHkgc2VudGVuY2UgXHUyMDE0IHRoZSB3aG9sZSBwb2ludCBvZiB0aGUgcmV3cml0ZSBpcyB0aGF0IHRoZSBtZXNzYWdlIHNheXNcbiAqIHdoYXQgKnRoaXMqIHJ1biBjYW4gYW5kIGNhbm5vdCBkbyBhYm91dCB0aGUgc2VydmVyIGl0IGZvdW5kLlxuICovXG5leHBvcnQgdHlwZSBXZWRnZWRBcHBpdW1TZXJ2ZXJSZXBvcnRSZWFzb24gPVxuICB8ICdhdXRvLXN0YXJ0LWRpc2FibGVkJ1xuICB8ICdmb3JlaWduLXNlcnZlcidcbiAgfCAnZnJlc2hseS1zdGFydGVkJ1xuICB8ICdyZXN0YXJ0LWRpZC1ub3QtaGVscCc7XG5cbi8qKlxuICogVGhlIHZlcmRpY3Qgb24gYSBmYWlsZWQgc2Vzc2lvbiBhdHRlbXB0LCBkaXNjcmltaW5hdGVkIGJ5IGByZW1lZHlgIHNvIGFcbiAqIGAncmVwb3J0J2AgdmVyZGljdCBjYXJyaWVzIGEgcmVhc29uIHtAbGluayBidWlsZFdlZGdlZEFwcGl1bVNlcnZlck1lc3NhZ2V9IGNhblxuICogdHVybiBpbnRvIGFkdmljZS5cbiAqL1xuZXhwb3J0IHR5cGUgV2VkZ2VkQXBwaXVtU2VydmVyVmVyZGljdCA9IE5vdFdlZGdlZFZlcmRpY3QgfCBSZXBvcnRTZXJ2ZXJWZXJkaWN0IHwgUmVzdGFydFNlcnZlclZlcmRpY3Q7XG5cbi8qKlxuICogQnVpbGRzIHRoZSBlcnJvciBtZXNzYWdlIHRoYXQgcmVwbGFjZXMgYENvdWxkIG5vdCBmaW5kIGEgY29ubmVjdGVkIEFuZHJvaWRcbiAqIGRldmljZWAsIG5hbWluZyB0aGUgKipzZXJ2ZXIqKiBhbmQgc3RhdGluZyB0aGUgZXZpZGVuY2UgXHUyMDE0IHRoZSBob3N0J3MgYWRiIGNhblxuICogc2VlIHRoZSBkZXZpY2UsIHNvIHRoZSBzZXJ2ZXIgaXMgdGhlIHRoaW5nIHRoYXQgaXMgc3RhbGUuXG4gKlxuICogQHBhcmFtIHBhcmFtcyAtIFRoZSBzZXJ2ZXIsIHRoZSBkZXZpY2UsIGFuZCB3aHkgdGhpcyBydW4gaXMgbm90IHJlc3RhcnRpbmcgaXQuXG4gKiBAcmV0dXJucyBUaGUgbWVzc2FnZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkV2VkZ2VkQXBwaXVtU2VydmVyTWVzc2FnZShwYXJhbXM6IEJ1aWxkV2VkZ2VkQXBwaXVtU2VydmVyTWVzc2FnZVBhcmFtcyk6IHN0cmluZyB7XG4gIGNvbnN0IGxpbmVzID0gW1xuICAgIGBUaGUgQXBwaXVtIHNlcnZlciBhdCAke3BhcmFtcy5hcHBpdW1PcmlnaW59IGNhbm5vdCBzZWUgQW5kcm9pZCBkZXZpY2UgJHtwYXJhbXMuZGV2aWNlSWR9LCBhbHRob3VnaCB0aGlzIGhvc3QncyBhZGIgY2FuLmAsXG4gICAgJ1RoZSBzZXJ2ZXIgaXMgc3RhbGUgXHUyMDE0IGl0cyBhZGIgY29ubmVjdGlvbiBpcyB3ZWRnZWQgXHUyMDE0IG5vdCB0aGUgZGV2aWNlLCBzbyBgYWRiIGRldmljZXNgIHdpbGwgbGlzdCB0aGUgZGV2aWNlIGFuZCBtaXNsZWFkIHlvdS4nLFxuICAgIHJlc29sdmVSZW1lZHlBZHZpY2UocGFyYW1zKVxuICBdO1xuXG4gIGNvbnN0IHByb3ZlbmFuY2UgPSBkZXNjcmliZVNlcnZlcihwYXJhbXMpO1xuICBpZiAocHJvdmVuYW5jZSkge1xuICAgIGxpbmVzLnB1c2gocHJvdmVuYW5jZSk7XG4gIH1cblxuICByZXR1cm4gbGluZXMuam9pbignXFxuJyk7XG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYSBmYWlsZWQgc2Vzc2lvbiBhdHRlbXB0IGlzIGBhcHBpdW0tYWRiYCdzIGRldmljZS1lbnVtZXJhdGlvblxuICogZmFpbHVyZS4gVGhlIHdob2xlIGBjYXVzZWAgY2hhaW4gaXMgc2VhcmNoZWQsIHNvIFdlYmRyaXZlcklPJ3Mgd3JhcHBpbmcgb2YgdGhlXG4gKiBzZXJ2ZXIncyBlcnJvciBkb2VzIG5vdCBoaWRlIGl0LlxuICpcbiAqIEBwYXJhbSBlcnJvciAtIFRoZSBlcnJvciB0aGUgc2Vzc2lvbiBhdHRlbXB0IGZhaWxlZCB3aXRoLlxuICogQHJldHVybnMgYHRydWVgIHdoZW4gaXQgaXMgdGhlIGRldmljZS1ub3QtZm91bmQgZmFpbHVyZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNoZWNrSXNBcHBpdW1EZXZpY2VOb3RGb3VuZEVycm9yKGVycm9yOiB1bmtub3duKTogYm9vbGVhbiB7XG4gIHJldHVybiBlcnJvclRvU3RyaW5nKGVycm9yKS5pbmNsdWRlcyhERVZJQ0VfTk9UX0ZPVU5EX01FU1NBR0VfRlJBR01FTlQpO1xufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIGFuIEFwcGl1bSBgL3N0YXR1c2AgYm9keSByZXBvcnRzIGEgc2VydmVyIHRoYXQgaXMgYWNjZXB0aW5nIG5ld1xuICogc2Vzc2lvbnMuXG4gKlxuICogRGVsaWJlcmF0ZWx5ICoqdG9sZXJhbnQqKjogb25seSBhbiBleHBsaWNpdCBgcmVhZHk6IGZhbHNlYCAoQXBwaXVtIHNldHMgaXRcbiAqIHdoaWxlIHNodXR0aW5nIGRvd24pIGlzIHRyZWF0ZWQgYXMgbm90LXJlYWR5LiBBIGJvZHkgdGhhdCBjYW5ub3QgYmUgcGFyc2VkLCBvclxuICogdGhhdCBvbWl0cyB0aGUgZmxhZywgcmVhZHMgYXMgcmVhZHkgXHUyMDE0IGFuIHVucmVjb2duaXplZCBzaGFwZSBtdXN0IG5vdCBtYWtlIGFcbiAqIGhlYWx0aHkgc2VydmVyIGxvb2sgdW5yZWFjaGFibGUuXG4gKlxuICogVGhpcyBkb2VzIG5vdCBjYXRjaCB0aGUgd2VkZ2UgKGEgd2VkZ2VkIHNlcnZlciBzdGlsbCBhbnN3ZXJzIGByZWFkeTogdHJ1ZWApO1xuICogaXQgY2xvc2VzIHRoZSBhZGphY2VudCBob2xlIG9mIGFkb3B0aW5nIGEgc2VydmVyIHRoYXQgaXMgb24gaXRzIHdheSBkb3duLlxuICpcbiAqIEBwYXJhbSBzdGF0dXNCb2R5IC0gVGhlIHJhdyBgL3N0YXR1c2AgcmVzcG9uc2UgYm9keS5cbiAqIEByZXR1cm5zIGBmYWxzZWAgb25seSB3aGVuIHRoZSBzZXJ2ZXIgZXhwbGljaXRseSByZXBvcnRzIGl0c2VsZiBub3QgcmVhZHkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjaGVja0lzQXBwaXVtU3RhdHVzUmVhZHkoc3RhdHVzQm9keTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGxldCBwYXJzZWQ6IHVua25vd247XG4gIHRyeSB7XG4gICAgcGFyc2VkID0gSlNPTi5wYXJzZShzdGF0dXNCb2R5KTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICByZXR1cm4gcmVhZFJlYWR5RmxhZyhwYXJzZWQpICE9PSBmYWxzZTtcbn1cblxuLyoqXG4gKiBEZWNpZGVzIHdoYXQgdG8gZG8gd2l0aCBhIGZhaWxlZCBzZXNzaW9uIGF0dGVtcHQuXG4gKlxuICogVGhlIGRldmljZS1ub3QtZm91bmQgZXJyb3IgaXMgb25seSBldmlkZW5jZSBhZ2FpbnN0IHRoZSBzZXJ2ZXIgd2hlbiB0aGUgaG9zdCdzXG4gKiBhZGIgKmNhbiogc3RpbGwgc2VlIHRoZSBkZXZpY2U7IG90aGVyd2lzZSB0aGUgZXJyb3Igd2FzIGhvbmVzdCBhbmQgaXMgbGVmdFxuICogYWxvbmUuIEEgc2VydmVyIHRoaXMgaGFybmVzcyBzdGFydGVkIGluIGFuIGVhcmxpZXIgcnVuIGlzIHJlc3RhcnRlZCAodGhlXG4gKiBjb25maXJtZWQgcmVtZWR5KTsgZXZlcnkgb3RoZXIgd2VkZ2VkIHNlcnZlciBpcyByZXBvcnRlZCByYXRoZXIgdGhhbiBraWxsZWQsXG4gKiBiZWNhdXNlIHRlcm1pbmF0aW5nIGEgcHJvY2VzcyB0aGlzIHJ1biBkb2VzIG5vdCBvd24gaXMgbm90IGl0cyBjYWxsIHRvIG1ha2UuXG4gKlxuICogQHBhcmFtIHBhcmFtcyAtIFRoZSBmYWlsZWQgYXR0ZW1wdCBhbmQgd2hhdCBpcyBrbm93biBhYm91dCB0aGUgc2VydmVyLlxuICogQHJldHVybnMgVGhlIHZlcmRpY3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlV2VkZ2VkQXBwaXVtU2VydmVyUmVtZWR5KHBhcmFtczogUmVzb2x2ZVdlZGdlZEFwcGl1bVNlcnZlclJlbWVkeVBhcmFtcyk6IFdlZGdlZEFwcGl1bVNlcnZlclZlcmRpY3Qge1xuICBpZiAoIWNoZWNrSXNBcHBpdW1EZXZpY2VOb3RGb3VuZEVycm9yKHBhcmFtcy5lcnJvcikpIHtcbiAgICByZXR1cm4geyByZWFzb246ICdvdGhlci1lcnJvcicsIHJlbWVkeTogJ25vdC13ZWRnZWQnIH07XG4gIH1cblxuICBpZiAoIXBhcmFtcy5jb25uZWN0ZWREZXZpY2VJZHMuaW5jbHVkZXMocGFyYW1zLmRldmljZUlkKSkge1xuICAgIHJldHVybiB7IHJlYXNvbjogJ2RldmljZS1hYnNlbnQnLCByZW1lZHk6ICdub3Qtd2VkZ2VkJyB9O1xuICB9XG5cbiAgaWYgKCFwYXJhbXMuaXNBZG9wdGVkU2VydmVyKSB7XG4gICAgcmV0dXJuIHsgcmVhc29uOiAnZnJlc2hseS1zdGFydGVkJywgcmVtZWR5OiAncmVwb3J0JyB9O1xuICB9XG5cbiAgaWYgKCFwYXJhbXMuaXNBdXRvU3RhcnRBbGxvd2VkKSB7XG4gICAgcmV0dXJuIHsgcmVhc29uOiAnYXV0by1zdGFydC1kaXNhYmxlZCcsIHJlbWVkeTogJ3JlcG9ydCcgfTtcbiAgfVxuXG4gIGlmICghcGFyYW1zLmlzSGFybmVzc093bmVkU2VydmVyKSB7XG4gICAgcmV0dXJuIHsgcmVhc29uOiAnZm9yZWlnbi1zZXJ2ZXInLCByZW1lZHk6ICdyZXBvcnQnIH07XG4gIH1cblxuICByZXR1cm4geyByZWFzb246ICdoYXJuZXNzLW93bmVkJywgcmVtZWR5OiAncmVzdGFydCcgfTtcbn1cblxuZnVuY3Rpb24gZGVzY3JpYmVTZXJ2ZXIocGFyYW1zOiBCdWlsZFdlZGdlZEFwcGl1bVNlcnZlck1lc3NhZ2VQYXJhbXMpOiBzdHJpbmcge1xuICBpZiAocGFyYW1zLnNlcnZlclBpZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgY29uc3QgYWdlID0gcGFyYW1zLnNlcnZlckFnZUluTWlsbGlzZWNvbmRzID09PSB1bmRlZmluZWQgPyAnJyA6IGAsIHJ1bm5pbmcgZm9yICR7Zm9ybWF0QWdlKHBhcmFtcy5zZXJ2ZXJBZ2VJbk1pbGxpc2Vjb25kcyl9YDtcbiAgcmV0dXJuIGBUaGUgc2VydmVyIHdhcyBzdGFydGVkIGJ5IGFuIGVhcmxpZXIgb2JzaWRpYW4taW50ZWdyYXRpb24tdGVzdGluZyBydW4gKHBpZCAke1N0cmluZyhwYXJhbXMuc2VydmVyUGlkKX0ke2FnZX0pLmA7XG59XG5cbmZ1bmN0aW9uIGZvcm1hdEFnZShhZ2VJbk1pbGxpc2Vjb25kczogbnVtYmVyKTogc3RyaW5nIHtcbiAgaWYgKGFnZUluTWlsbGlzZWNvbmRzIDwgTUlMTElTRUNPTkRTX1BFUl9NSU5VVEUpIHtcbiAgICByZXR1cm4gYCR7U3RyaW5nKE1hdGgucm91bmQoYWdlSW5NaWxsaXNlY29uZHMgLyBNSUxMSVNFQ09ORFNfUEVSX1NFQ09ORCkpfXNgO1xuICB9XG5cbiAgcmV0dXJuIGAke1N0cmluZyhNYXRoLnJvdW5kKGFnZUluTWlsbGlzZWNvbmRzIC8gTUlMTElTRUNPTkRTX1BFUl9NSU5VVEUpKX1taW5gO1xufVxuXG5mdW5jdGlvbiByZWFkUmVhZHlGbGFnKHBhcnNlZDogdW5rbm93bik6IGJvb2xlYW4gfCB1bmRlZmluZWQge1xuICBpZiAodHlwZW9mIHBhcnNlZCAhPT0gJ29iamVjdCcgfHwgcGFyc2VkID09PSBudWxsKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIGNvbnN0IHJlY29yZCA9IHBhcnNlZCBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgY29uc3QgdmFsdWUgPSByZWNvcmRbJ3ZhbHVlJ107XG4gIGNvbnN0IG5lc3RlZCA9IHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgdmFsdWUgIT09IG51bGwgPyAodmFsdWUgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pWydyZWFkeSddIDogdW5kZWZpbmVkO1xuICBjb25zdCByZWFkeSA9IG5lc3RlZCA/PyByZWNvcmRbJ3JlYWR5J107XG4gIHJldHVybiB0eXBlb2YgcmVhZHkgPT09ICdib29sZWFuJyA/IHJlYWR5IDogdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiByZXNvbHZlUmVtZWR5QWR2aWNlKHBhcmFtczogQnVpbGRXZWRnZWRBcHBpdW1TZXJ2ZXJNZXNzYWdlUGFyYW1zKTogc3RyaW5nIHtcbiAgY29uc3QgYWR2aWNlOiBSZWNvcmQ8V2VkZ2VkQXBwaXVtU2VydmVyUmVwb3J0UmVhc29uLCBzdHJpbmc+ID0ge1xuICAgICdhdXRvLXN0YXJ0LWRpc2FibGVkJzogYEFwcGl1bSBhdXRvLXN0YXJ0IGlzIGRpc2FibGVkIChcXGBzaG91bGRBdXRvU3RhcnRBcHBpdW06IGZhbHNlXFxgKSwgc28gdGhpcyBzZXJ2ZXIgaXMgeW91cnMgdG8gbWFuYWdlOiBraWxsIGl0IGFuZCBzdGFydCBhIGZyZXNoIG9uZSBvbiAke3BhcmFtcy5hcHBpdW1PcmlnaW59LCB0aGVuIHJlLXJ1bi5gLFxuICAgICdmb3JlaWduLXNlcnZlcic6IGBUaGlzIHNlcnZlciB3YXMgbm90IHN0YXJ0ZWQgYnkgb2JzaWRpYW4taW50ZWdyYXRpb24tdGVzdGluZywgc28gaXQgd2FzIGxlZnQgcnVubmluZzoga2lsbCBpdCBhbmQgc3RhcnQgYSBmcmVzaCBvbmUgb24gJHtwYXJhbXMuYXBwaXVtT3JpZ2lufSwgdGhlbiByZS1ydW4uYCxcbiAgICAnZnJlc2hseS1zdGFydGVkJzogJ1RoaXMgc2VydmVyIHdhcyBzdGFydGVkIGJ5IHRoaXMgcnVuLCBzbyByZXN0YXJ0aW5nIGl0IHdvdWxkIGNoYW5nZSBub3RoaW5nOiBjaGVjayB0aGF0IGFkYiBhbmQgdGhlIGVtdWxhdG9yIGFncmVlIChgYWRiIGtpbGwtc2VydmVyICYmIGFkYiBkZXZpY2VzYCksIHRoZW4gcmUtcnVuLicsXG4gICAgJ3Jlc3RhcnQtZGlkLW5vdC1oZWxwJzogYFJlc3RhcnRpbmcgdGhlIHNlcnZlciBvbiAke3BhcmFtcy5hcHBpdW1PcmlnaW59IGRpZCBub3QgaGVscCBcdTIwMTQgYSBmcmVzaCBvbmUgc3RpbGwgY291bGQgbm90IHNlcnZlIHRoaXMgcnVuLCBzbyB0aGUgd2VkZ2UgaXMgbm90IHRoZSBzZXJ2ZXIgYWxvbmU6IGNoZWNrIGFkYiBpdHNlbGYgKFxcYGFkYiBraWxsLXNlcnZlciAmJiBhZGIgZGV2aWNlc1xcYCkgYW5kIHRoYXQgbm90aGluZyBlbHNlIGhvbGRzIHRoZSBwb3J0LCB0aGVuIHJlLXJ1bi5gXG4gIH07XG5cbiAgcmV0dXJuIGFkdmljZVtwYXJhbXMucmVhc29uXTtcbn1cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFB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
@@ -0,0 +1,187 @@
1
+ /**
2
+ * @file
3
+ *
4
+ * Pure helpers for recognizing a **wedged** Appium server and deciding what to
5
+ * do about it. Kept separate from the integration-only `transport-factory` so
6
+ * the classification, the remedy decision and the message stay unit-testable
7
+ * (the factory itself needs a real device and is excluded from unit tests).
8
+ *
9
+ * A wedged server is one that is still **live** — it listens on its port and
10
+ * answers `/status` with `ready: true` — but is no longer **usable**: its
11
+ * `appium-adb` can no longer enumerate devices, so every session creation dies
12
+ * with `Could not find a connected Android device in <n>ms` while the host's own
13
+ * `adb devices` lists the device instantly. Liveness is not readiness, and the
14
+ * error names the wrong subject: it blames a device that is demonstrably
15
+ * present, which sends whoever reads it to `adb devices` — the one diagnostic
16
+ * that actively misleads here.
17
+ *
18
+ * The wedge develops over time in a long-lived server (one auto-started by an
19
+ * earlier run and left listening), so the preflight cannot see it coming: it can
20
+ * only be recognized from the failed session, cross-checked against the host's
21
+ * adb.
22
+ */
23
+ /**
24
+ * Parameters for {@link buildWedgedAppiumServerMessage}.
25
+ */
26
+ export interface BuildWedgedAppiumServerMessageParams {
27
+ /**
28
+ Origin of the Appium server that could not see the device (e.g. `http://localhost:4723`).
29
+ */
30
+ readonly appiumOrigin: string;
31
+ /**
32
+ The device the host's adb can see but Appium cannot.
33
+ */
34
+ readonly deviceId: string;
35
+ /**
36
+ Why this run is reporting rather than restarting.
37
+ */
38
+ readonly reason: WedgedAppiumServerReportReason;
39
+ /**
40
+ How long the server has been running, when known from its marker.
41
+ */
42
+ readonly serverAgeInMilliseconds?: number | undefined;
43
+ /**
44
+ PID of the server, when known from its marker.
45
+ */
46
+ readonly serverPid?: number | undefined;
47
+ }
48
+ /**
49
+ * The server is not to blame: either the failure was a different error, or the
50
+ * host's adb cannot see the device either. The original error is rethrown.
51
+ */
52
+ export interface NotWedgedVerdict {
53
+ /**
54
+ Which of the two honest-failure cases this is.
55
+ */
56
+ readonly reason: 'device-absent' | 'other-error';
57
+ /**
58
+ Discriminant.
59
+ */
60
+ readonly remedy: 'not-wedged';
61
+ }
62
+ /**
63
+ * The server is wedged but must not be touched by this run.
64
+ */
65
+ export interface ReportServerVerdict {
66
+ /**
67
+ Why this run is reporting rather than restarting.
68
+ */
69
+ readonly reason: WedgedAppiumServerReportReason;
70
+ /**
71
+ Discriminant.
72
+ */
73
+ readonly remedy: 'report';
74
+ }
75
+ /**
76
+ * Parameters for {@link resolveWedgedAppiumServerRemedy}.
77
+ */
78
+ export interface ResolveWedgedAppiumServerRemedyParams {
79
+ /**
80
+ Device IDs the **host's** adb currently lists (the cross-check that convicts the server).
81
+ */
82
+ readonly connectedDeviceIds: readonly string[];
83
+ /**
84
+ The device the session was requested against.
85
+ */
86
+ readonly deviceId: string;
87
+ /**
88
+ The error the session attempt failed with.
89
+ */
90
+ readonly error: unknown;
91
+ /**
92
+ Whether the server was already listening and was adopted, rather than started by this run.
93
+ */
94
+ readonly isAdoptedServer: boolean;
95
+ /**
96
+ Whether this run may start an Appium server (`shouldAutoStartAppium` is not `false`).
97
+ */
98
+ readonly isAutoStartAllowed: boolean;
99
+ /**
100
+ Whether the adopted server's marker proves an earlier run of this harness started it.
101
+ */
102
+ readonly isHarnessOwnedServer: boolean;
103
+ }
104
+ /**
105
+ * The server is wedged and an earlier run of this harness started it, so this
106
+ * run may replace it.
107
+ */
108
+ export interface RestartServerVerdict {
109
+ /**
110
+ Always the harness-owned case.
111
+ */
112
+ readonly reason: 'harness-owned';
113
+ /**
114
+ Discriminant.
115
+ */
116
+ readonly remedy: 'restart';
117
+ }
118
+ /**
119
+ * The classification of a failed session attempt.
120
+ *
121
+ * `'device-absent'` and `'other-error'` are the not-wedged verdicts: the
122
+ * original error was honest and is rethrown untouched.
123
+ */
124
+ export type WedgedAppiumServerReason = 'device-absent' | 'harness-owned' | 'other-error' | WedgedAppiumServerReportReason;
125
+ /**
126
+ * What the factory should do with a failed session attempt.
127
+ */
128
+ export type WedgedAppiumServerRemedy = 'not-wedged' | 'report' | 'restart';
129
+ /**
130
+ * Why a wedged server is only reported rather than restarted. Each maps to its
131
+ * own remedy sentence — the whole point of the rewrite is that the message says
132
+ * what *this* run can and cannot do about the server it found.
133
+ */
134
+ export type WedgedAppiumServerReportReason = 'auto-start-disabled' | 'foreign-server' | 'freshly-started' | 'restart-did-not-help';
135
+ /**
136
+ * The verdict on a failed session attempt, discriminated by `remedy` so a
137
+ * `'report'` verdict carries a reason {@link buildWedgedAppiumServerMessage} can
138
+ * turn into advice.
139
+ */
140
+ export type WedgedAppiumServerVerdict = NotWedgedVerdict | ReportServerVerdict | RestartServerVerdict;
141
+ /**
142
+ * Builds the error message that replaces `Could not find a connected Android
143
+ * device`, naming the **server** and stating the evidence — the host's adb can
144
+ * see the device, so the server is the thing that is stale.
145
+ *
146
+ * @param params - The server, the device, and why this run is not restarting it.
147
+ * @returns The message.
148
+ */
149
+ export declare function buildWedgedAppiumServerMessage(params: BuildWedgedAppiumServerMessageParams): string;
150
+ /**
151
+ * Checks whether a failed session attempt is `appium-adb`'s device-enumeration
152
+ * failure. The whole `cause` chain is searched, so WebdriverIO's wrapping of the
153
+ * server's error does not hide it.
154
+ *
155
+ * @param error - The error the session attempt failed with.
156
+ * @returns `true` when it is the device-not-found failure.
157
+ */
158
+ export declare function checkIsAppiumDeviceNotFoundError(error: unknown): boolean;
159
+ /**
160
+ * Checks whether an Appium `/status` body reports a server that is accepting new
161
+ * sessions.
162
+ *
163
+ * Deliberately **tolerant**: only an explicit `ready: false` (Appium sets it
164
+ * while shutting down) is treated as not-ready. A body that cannot be parsed, or
165
+ * that omits the flag, reads as ready — an unrecognized shape must not make a
166
+ * healthy server look unreachable.
167
+ *
168
+ * This does not catch the wedge (a wedged server still answers `ready: true`);
169
+ * it closes the adjacent hole of adopting a server that is on its way down.
170
+ *
171
+ * @param statusBody - The raw `/status` response body.
172
+ * @returns `false` only when the server explicitly reports itself not ready.
173
+ */
174
+ export declare function checkIsAppiumStatusReady(statusBody: string): boolean;
175
+ /**
176
+ * Decides what to do with a failed session attempt.
177
+ *
178
+ * The device-not-found error is only evidence against the server when the host's
179
+ * adb *can* still see the device; otherwise the error was honest and is left
180
+ * alone. A server this harness started in an earlier run is restarted (the
181
+ * confirmed remedy); every other wedged server is reported rather than killed,
182
+ * because terminating a process this run does not own is not its call to make.
183
+ *
184
+ * @param params - The failed attempt and what is known about the server.
185
+ * @returns The verdict.
186
+ */
187
+ export declare function resolveWedgedAppiumServerRemedy(params: ResolveWedgedAppiumServerRemedyParams): WedgedAppiumServerVerdict;
@@ -0,0 +1,81 @@
1
+ /**
2
+ * @file
3
+ *
4
+ * Records which Appium server on a port this harness started, so a later run
5
+ * that finds a server already listening can tell **provenance**: one of our own
6
+ * servers left over from an earlier run, or a foreign one the user manages.
7
+ *
8
+ * The preflight adopts any server that answers `/status`, and adoption is the
9
+ * right default — starting a second server on an occupied port cannot work. But
10
+ * adopting silently means a wedged leftover (see `wedged-appium-server.ts`) is
11
+ * indistinguishable from a healthy server, and the harness has no basis on which
12
+ * to decide whether restarting it is its call to make. The marker supplies that
13
+ * basis: a server we started may be restarted, a foreign one is only ever
14
+ * reported.
15
+ *
16
+ * The marker is a small JSON sentinel next to the setup lock (`setup-lock.ts`),
17
+ * keyed by port, and is deliberately tolerant — a missing, unreadable, or
18
+ * mismatched marker simply reads as "not ours".
19
+ */
20
+ /**
21
+ * Identifies the Appium server this harness started on a port.
22
+ */
23
+ export interface AppiumServerMarker {
24
+ /**
25
+ PID of the spawned server process (the shell wrapper that owns the server's process tree).
26
+ */
27
+ readonly pid: number;
28
+ /**
29
+ The port the server was started on.
30
+ */
31
+ readonly port: number;
32
+ /**
33
+ When the server was started (`Date.now()` epoch milliseconds).
34
+ */
35
+ readonly startedAtInMilliseconds: number;
36
+ }
37
+ /**
38
+ * Parameters for {@link writeAppiumServerMarker}.
39
+ */
40
+ export interface WriteAppiumServerMarkerParams {
41
+ /**
42
+ PID of the spawned server process.
43
+ */
44
+ readonly pid: number;
45
+ /**
46
+ The port the server was started on.
47
+ */
48
+ readonly port: number;
49
+ }
50
+ /**
51
+ * Checks whether the marked server is still running, which is what makes an
52
+ * adopted server ours to restart.
53
+ *
54
+ * A dead PID means the marker outlived its server, so whatever answers on that
55
+ * port now is somebody else's — the marker proves nothing about it.
56
+ *
57
+ * @param marker - The marker read for the port, or `undefined` when there is none.
58
+ * @returns `true` when an earlier run of this harness started the server now listening.
59
+ */
60
+ export declare function checkIsHarnessOwnedAppiumServer(marker: AppiumServerMarker | undefined): boolean;
61
+ /**
62
+ * Removes the marker for a port. Called once the marked server has been stopped,
63
+ * so a later run does not mistake a recycled PID for our server.
64
+ *
65
+ * @param port - The Appium server port.
66
+ */
67
+ export declare function clearAppiumServerMarker(port: number): void;
68
+ /**
69
+ * Reads the marker for a port.
70
+ *
71
+ * @param port - The Appium server port.
72
+ * @returns The marker, or `undefined` when there is none, it is unreadable, or it does not describe this port.
73
+ */
74
+ export declare function readAppiumServerMarker(port: number): AppiumServerMarker | undefined;
75
+ /**
76
+ * Records the server this run just started, stamping it with the current time so
77
+ * a later run can report how long it has been up.
78
+ *
79
+ * @param params - The started server's PID and port.
80
+ */
81
+ export declare function writeAppiumServerMarker(params: WriteAppiumServerMarkerParams): void;
@@ -0,0 +1,83 @@
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 process from "node:process";
10
+ import { log } from "./log.mjs";
11
+ const MARKER_DIR_NAME = "obsidian-integration-testing";
12
+ const MARKER_FILE_SUFFIX = ".appium-server.json";
13
+ const PROCESS_EXISTENCE_PROBE_SIGNAL = 0;
14
+ function checkIsHarnessOwnedAppiumServer(marker) {
15
+ if (!marker) {
16
+ return false;
17
+ }
18
+ try {
19
+ process.kill(marker.pid, PROCESS_EXISTENCE_PROBE_SIGNAL);
20
+ return true;
21
+ } catch (error) {
22
+ return getErrorCode(error) === "EPERM";
23
+ }
24
+ }
25
+ function clearAppiumServerMarker(port) {
26
+ try {
27
+ rmSync(getMarkerFilePath(port), { force: true });
28
+ } catch (error) {
29
+ log(`[appium-server-marker] Could not remove the marker for port ${String(port)}: ${getErrorMessage(error)}`);
30
+ }
31
+ }
32
+ function readAppiumServerMarker(port) {
33
+ let parsed;
34
+ try {
35
+ parsed = JSON.parse(readFileSync(getMarkerFilePath(port), "utf-8"));
36
+ } catch {
37
+ return void 0;
38
+ }
39
+ return parseMarker(parsed, port);
40
+ }
41
+ function writeAppiumServerMarker(params) {
42
+ const marker = {
43
+ pid: params.pid,
44
+ port: params.port,
45
+ startedAtInMilliseconds: Date.now()
46
+ };
47
+ try {
48
+ mkdirSync(getMarkerDirectory(), { recursive: true });
49
+ writeFileSync(getMarkerFilePath(params.port), JSON.stringify(marker));
50
+ } catch (error) {
51
+ log(`[appium-server-marker] Could not record the server on port ${String(params.port)}: ${getErrorMessage(error)}`);
52
+ }
53
+ }
54
+ function getErrorCode(error) {
55
+ return typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0;
56
+ }
57
+ function getErrorMessage(error) {
58
+ return error instanceof Error ? error.message : String(error);
59
+ }
60
+ function getMarkerDirectory() {
61
+ return join(tmpdir(), MARKER_DIR_NAME);
62
+ }
63
+ function getMarkerFilePath(port) {
64
+ return join(getMarkerDirectory(), `${String(port)}${MARKER_FILE_SUFFIX}`);
65
+ }
66
+ function parseMarker(parsed, port) {
67
+ if (typeof parsed !== "object" || parsed === null) {
68
+ return void 0;
69
+ }
70
+ const record = parsed;
71
+ const { pid, port: markedPort, startedAtInMilliseconds } = record;
72
+ if (typeof pid !== "number" || typeof startedAtInMilliseconds !== "number" || markedPort !== port) {
73
+ return void 0;
74
+ }
75
+ return { pid, port, startedAtInMilliseconds };
76
+ }
77
+ export {
78
+ checkIsHarnessOwnedAppiumServer,
79
+ clearAppiumServerMarker,
80
+ readAppiumServerMarker,
81
+ writeAppiumServerMarker
82
+ };
83
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2FwcGl1bS1zZXJ2ZXItbWFya2VyLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBmaWxlXG4gKlxuICogUmVjb3JkcyB3aGljaCBBcHBpdW0gc2VydmVyIG9uIGEgcG9ydCB0aGlzIGhhcm5lc3Mgc3RhcnRlZCwgc28gYSBsYXRlciBydW5cbiAqIHRoYXQgZmluZHMgYSBzZXJ2ZXIgYWxyZWFkeSBsaXN0ZW5pbmcgY2FuIHRlbGwgKipwcm92ZW5hbmNlKio6IG9uZSBvZiBvdXIgb3duXG4gKiBzZXJ2ZXJzIGxlZnQgb3ZlciBmcm9tIGFuIGVhcmxpZXIgcnVuLCBvciBhIGZvcmVpZ24gb25lIHRoZSB1c2VyIG1hbmFnZXMuXG4gKlxuICogVGhlIHByZWZsaWdodCBhZG9wdHMgYW55IHNlcnZlciB0aGF0IGFuc3dlcnMgYC9zdGF0dXNgLCBhbmQgYWRvcHRpb24gaXMgdGhlXG4gKiByaWdodCBkZWZhdWx0IFx1MjAxNCBzdGFydGluZyBhIHNlY29uZCBzZXJ2ZXIgb24gYW4gb2NjdXBpZWQgcG9ydCBjYW5ub3Qgd29yay4gQnV0XG4gKiBhZG9wdGluZyBzaWxlbnRseSBtZWFucyBhIHdlZGdlZCBsZWZ0b3ZlciAoc2VlIGB3ZWRnZWQtYXBwaXVtLXNlcnZlci50c2ApIGlzXG4gKiBpbmRpc3Rpbmd1aXNoYWJsZSBmcm9tIGEgaGVhbHRoeSBzZXJ2ZXIsIGFuZCB0aGUgaGFybmVzcyBoYXMgbm8gYmFzaXMgb24gd2hpY2hcbiAqIHRvIGRlY2lkZSB3aGV0aGVyIHJlc3RhcnRpbmcgaXQgaXMgaXRzIGNhbGwgdG8gbWFrZS4gVGhlIG1hcmtlciBzdXBwbGllcyB0aGF0XG4gKiBiYXNpczogYSBzZXJ2ZXIgd2Ugc3RhcnRlZCBtYXkgYmUgcmVzdGFydGVkLCBhIGZvcmVpZ24gb25lIGlzIG9ubHkgZXZlclxuICogcmVwb3J0ZWQuXG4gKlxuICogVGhlIG1hcmtlciBpcyBhIHNtYWxsIEpTT04gc2VudGluZWwgbmV4dCB0byB0aGUgc2V0dXAgbG9jayAoYHNldHVwLWxvY2sudHNgKSxcbiAqIGtleWVkIGJ5IHBvcnQsIGFuZCBpcyBkZWxpYmVyYXRlbHkgdG9sZXJhbnQgXHUyMDE0IGEgbWlzc2luZywgdW5yZWFkYWJsZSwgb3JcbiAqIG1pc21hdGNoZWQgbWFya2VyIHNpbXBseSByZWFkcyBhcyBcIm5vdCBvdXJzXCIuXG4gKi9cblxuaW1wb3J0IHtcbiAgbWtkaXJTeW5jLFxuICByZWFkRmlsZVN5bmMsXG4gIHJtU3luYyxcbiAgd3JpdGVGaWxlU3luY1xufSBmcm9tICdub2RlOmZzJztcbmltcG9ydCB7IHRtcGRpciB9IGZyb20gJ25vZGU6b3MnO1xuaW1wb3J0IHsgam9pbiB9IGZyb20gJ25vZGU6cGF0aCc7XG5pbXBvcnQgcHJvY2VzcyBmcm9tICdub2RlOnByb2Nlc3MnO1xuXG5pbXBvcnQgeyBsb2cgfSBmcm9tICcuL2xvZy5tanMnO1xuXG5jb25zdCBNQVJLRVJfRElSX05BTUUgPSAnb2JzaWRpYW4taW50ZWdyYXRpb24tdGVzdGluZyc7XG5jb25zdCBNQVJLRVJfRklMRV9TVUZGSVggPSAnLmFwcGl1bS1zZXJ2ZXIuanNvbic7XG5jb25zdCBQUk9DRVNTX0VYSVNURU5DRV9QUk9CRV9TSUdOQUwgPSAwO1xuXG4vKipcbiAqIElkZW50aWZpZXMgdGhlIEFwcGl1bSBzZXJ2ZXIgdGhpcyBoYXJuZXNzIHN0YXJ0ZWQgb24gYSBwb3J0LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEFwcGl1bVNlcnZlck1hcmtlciB7XG4gIC8qKlxuICBQSUQgb2YgdGhlIHNwYXduZWQgc2VydmVyIHByb2Nlc3MgKHRoZSBzaGVsbCB3cmFwcGVyIHRoYXQgb3ducyB0aGUgc2VydmVyJ3MgcHJvY2VzcyB0cmVlKS5cbiAgICovXG4gIHJlYWRvbmx5IHBpZDogbnVtYmVyO1xuXG4gIC8qKlxuICBUaGUgcG9ydCB0aGUgc2VydmVyIHdhcyBzdGFydGVkIG9uLlxuICAgKi9cbiAgcmVhZG9ubHkgcG9ydDogbnVtYmVyO1xuXG4gIC8qKlxuICBXaGVuIHRoZSBzZXJ2ZXIgd2FzIHN0YXJ0ZWQgKGBEYXRlLm5vdygpYCBlcG9jaCBtaWxsaXNlY29uZHMpLlxuICAgKi9cbiAgcmVhZG9ubHkgc3RhcnRlZEF0SW5NaWxsaXNlY29uZHM6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBQYXJhbWV0ZXJzIGZvciB7QGxpbmsgd3JpdGVBcHBpdW1TZXJ2ZXJNYXJrZXJ9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFdyaXRlQXBwaXVtU2VydmVyTWFya2VyUGFyYW1zIHtcbiAgLyoqXG4gIFBJRCBvZiB0aGUgc3Bhd25lZCBzZXJ2ZXIgcHJvY2Vzcy5cbiAgICovXG4gIHJlYWRvbmx5IHBpZDogbnVtYmVyO1xuXG4gIC8qKlxuICBUaGUgcG9ydCB0aGUgc2VydmVyIHdhcyBzdGFydGVkIG9uLlxuICAgKi9cbiAgcmVhZG9ubHkgcG9ydDogbnVtYmVyO1xufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIHRoZSBtYXJrZWQgc2VydmVyIGlzIHN0aWxsIHJ1bm5pbmcsIHdoaWNoIGlzIHdoYXQgbWFrZXMgYW5cbiAqIGFkb3B0ZWQgc2VydmVyIG91cnMgdG8gcmVzdGFydC5cbiAqXG4gKiBBIGRlYWQgUElEIG1lYW5zIHRoZSBtYXJrZXIgb3V0bGl2ZWQgaXRzIHNlcnZlciwgc28gd2hhdGV2ZXIgYW5zd2VycyBvbiB0aGF0XG4gKiBwb3J0IG5vdyBpcyBzb21lYm9keSBlbHNlJ3MgXHUyMDE0IHRoZSBtYXJrZXIgcHJvdmVzIG5vdGhpbmcgYWJvdXQgaXQuXG4gKlxuICogQHBhcmFtIG1hcmtlciAtIFRoZSBtYXJrZXIgcmVhZCBmb3IgdGhlIHBvcnQsIG9yIGB1bmRlZmluZWRgIHdoZW4gdGhlcmUgaXMgbm9uZS5cbiAqIEByZXR1cm5zIGB0cnVlYCB3aGVuIGFuIGVhcmxpZXIgcnVuIG9mIHRoaXMgaGFybmVzcyBzdGFydGVkIHRoZSBzZXJ2ZXIgbm93IGxpc3RlbmluZy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNoZWNrSXNIYXJuZXNzT3duZWRBcHBpdW1TZXJ2ZXIobWFya2VyOiBBcHBpdW1TZXJ2ZXJNYXJrZXIgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgaWYgKCFtYXJrZXIpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICB0cnkge1xuICAgIHByb2Nlc3Mua2lsbChtYXJrZXIucGlkLCBQUk9DRVNTX0VYSVNURU5DRV9QUk9CRV9TSUdOQUwpO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgIC8vIGBFUEVSTWAgbWVhbnMgdGhlIHByb2Nlc3MgZXhpc3RzIGJ1dCBpcyBvd25lZCBieSBhbm90aGVyIHVzZXIgXHUyMDE0IHN0aWxsIGFsaXZlLlxuICAgIHJldHVybiBnZXRFcnJvckNvZGUoZXJyb3IpID09PSAnRVBFUk0nO1xuICB9XG59XG5cbi8qKlxuICogUmVtb3ZlcyB0aGUgbWFya2VyIGZvciBhIHBvcnQuIENhbGxlZCBvbmNlIHRoZSBtYXJrZWQgc2VydmVyIGhhcyBiZWVuIHN0b3BwZWQsXG4gKiBzbyBhIGxhdGVyIHJ1biBkb2VzIG5vdCBtaXN0YWtlIGEgcmVjeWNsZWQgUElEIGZvciBvdXIgc2VydmVyLlxuICpcbiAqIEBwYXJhbSBwb3J0IC0gVGhlIEFwcGl1bSBzZXJ2ZXIgcG9ydC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsZWFyQXBwaXVtU2VydmVyTWFya2VyKHBvcnQ6IG51bWJlcik6IHZvaWQge1xuICB0cnkge1xuICAgIHJtU3luYyhnZXRNYXJrZXJGaWxlUGF0aChwb3J0KSwgeyBmb3JjZTogdHJ1ZSB9KTtcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICBsb2coYFthcHBpdW0tc2VydmVyLW1hcmtlcl0gQ291bGQgbm90IHJlbW92ZSB0aGUgbWFya2VyIGZvciBwb3J0ICR7U3RyaW5nKHBvcnQpfTogJHtnZXRFcnJvck1lc3NhZ2UoZXJyb3IpfWApO1xuICB9XG59XG5cbi8qKlxuICogUmVhZHMgdGhlIG1hcmtlciBmb3IgYSBwb3J0LlxuICpcbiAqIEBwYXJhbSBwb3J0IC0gVGhlIEFwcGl1bSBzZXJ2ZXIgcG9ydC5cbiAqIEByZXR1cm5zIFRoZSBtYXJrZXIsIG9yIGB1bmRlZmluZWRgIHdoZW4gdGhlcmUgaXMgbm9uZSwgaXQgaXMgdW5yZWFkYWJsZSwgb3IgaXQgZG9lcyBub3QgZGVzY3JpYmUgdGhpcyBwb3J0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVhZEFwcGl1bVNlcnZlck1hcmtlcihwb3J0OiBudW1iZXIpOiBBcHBpdW1TZXJ2ZXJNYXJrZXIgfCB1bmRlZmluZWQge1xuICBsZXQgcGFyc2VkOiB1bmtub3duO1xuICB0cnkge1xuICAgIHBhcnNlZCA9IEpTT04ucGFyc2UocmVhZEZpbGVTeW5jKGdldE1hcmtlckZpbGVQYXRoKHBvcnQpLCAndXRmLTgnKSk7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICByZXR1cm4gcGFyc2VNYXJrZXIocGFyc2VkLCBwb3J0KTtcbn1cblxuLyoqXG4gKiBSZWNvcmRzIHRoZSBzZXJ2ZXIgdGhpcyBydW4ganVzdCBzdGFydGVkLCBzdGFtcGluZyBpdCB3aXRoIHRoZSBjdXJyZW50IHRpbWUgc29cbiAqIGEgbGF0ZXIgcnVuIGNhbiByZXBvcnQgaG93IGxvbmcgaXQgaGFzIGJlZW4gdXAuXG4gKlxuICogQHBhcmFtIHBhcmFtcyAtIFRoZSBzdGFydGVkIHNlcnZlcidzIFBJRCBhbmQgcG9ydC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdyaXRlQXBwaXVtU2VydmVyTWFya2VyKHBhcmFtczogV3JpdGVBcHBpdW1TZXJ2ZXJNYXJrZXJQYXJhbXMpOiB2b2lkIHtcbiAgY29uc3QgbWFya2VyOiBBcHBpdW1TZXJ2ZXJNYXJrZXIgPSB7XG4gICAgcGlkOiBwYXJhbXMucGlkLFxuICAgIHBvcnQ6IHBhcmFtcy5wb3J0LFxuICAgIHN0YXJ0ZWRBdEluTWlsbGlzZWNvbmRzOiBEYXRlLm5vdygpXG4gIH07XG5cbiAgdHJ5IHtcbiAgICBta2RpclN5bmMoZ2V0TWFya2VyRGlyZWN0b3J5KCksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgIHdyaXRlRmlsZVN5bmMoZ2V0TWFya2VyRmlsZVBhdGgocGFyYW1zLnBvcnQpLCBKU09OLnN0cmluZ2lmeShtYXJrZXIpKTtcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICBsb2coYFthcHBpdW0tc2VydmVyLW1hcmtlcl0gQ291bGQgbm90IHJlY29yZCB0aGUgc2VydmVyIG9uIHBvcnQgJHtTdHJpbmcocGFyYW1zLnBvcnQpfTogJHtnZXRFcnJvck1lc3NhZ2UoZXJyb3IpfWApO1xuICB9XG59XG5cbmZ1bmN0aW9uIGdldEVycm9yQ29kZShlcnJvcjogdW5rbm93bik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiB0eXBlb2YgZXJyb3IgPT09ICdvYmplY3QnICYmIGVycm9yICE9PSBudWxsICYmICdjb2RlJyBpbiBlcnJvciA/IFN0cmluZyhlcnJvci5jb2RlKSA6IHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gZ2V0RXJyb3JNZXNzYWdlKGVycm9yOiB1bmtub3duKTogc3RyaW5nIHtcbiAgcmV0dXJuIGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKTtcbn1cblxuZnVuY3Rpb24gZ2V0TWFya2VyRGlyZWN0b3J5KCk6IHN0cmluZyB7XG4gIHJldHVybiBqb2luKHRtcGRpcigpLCBNQVJLRVJfRElSX05BTUUpO1xufVxuXG5mdW5jdGlvbiBnZXRNYXJrZXJGaWxlUGF0aChwb3J0OiBudW1iZXIpOiBzdHJpbmcge1xuICByZXR1cm4gam9pbihnZXRNYXJrZXJEaXJlY3RvcnkoKSwgYCR7U3RyaW5nKHBvcnQpfSR7TUFSS0VSX0ZJTEVfU1VGRklYfWApO1xufVxuXG5mdW5jdGlvbiBwYXJzZU1hcmtlcihwYXJzZWQ6IHVua25vd24sIHBvcnQ6IG51bWJlcik6IEFwcGl1bVNlcnZlck1hcmtlciB8IHVuZGVmaW5lZCB7XG4gIGlmICh0eXBlb2YgcGFyc2VkICE9PSAnb2JqZWN0JyB8fCBwYXJzZWQgPT09IG51bGwpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgY29uc3QgcmVjb3JkID0gcGFyc2VkIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBjb25zdCB7IHBpZCwgcG9ydDogbWFya2VkUG9ydCwgc3RhcnRlZEF0SW5NaWxsaXNlY29uZHMgfSA9IHJlY29yZDtcblxuICBpZiAodHlwZW9mIHBpZCAhPT0gJ251bWJlcicgfHwgdHlwZW9mIHN0YXJ0ZWRBdEluTWlsbGlzZWNvbmRzICE9PSAnbnVtYmVyJyB8fCBtYXJrZWRQb3J0ICE9PSBwb3J0KSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHJldHVybiB7IHBpZCwgcG9ydCwgc3RhcnRlZEF0SW5NaWxsaXNlY29uZHMgfTtcbn1cbiJdLAogICJtYXBwaW5ncyI6ICJBQW9CQTtBQUFBLEVBQ0U7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxPQUNLO0FBQ1AsU0FBUyxjQUFjO0FBQ3ZCLFNBQVMsWUFBWTtBQUNyQixPQUFPLGFBQWE7QUFFcEIsU0FBUyxXQUFXO0FBRXBCLE1BQU0sa0JBQWtCO0FBQ3hCLE1BQU0scUJBQXFCO0FBQzNCLE1BQU0saUNBQWlDO0FBK0NoQyxTQUFTLGdDQUFnQyxRQUFpRDtBQUMvRixNQUFJLENBQUMsUUFBUTtBQUNYLFdBQU87QUFBQSxFQUNUO0FBRUEsTUFBSTtBQUNGLFlBQVEsS0FBSyxPQUFPLEtBQUssOEJBQThCO0FBQ3ZELFdBQU87QUFBQSxFQUNULFNBQVMsT0FBZ0I7QUFFdkIsV0FBTyxhQUFhLEtBQUssTUFBTTtBQUFBLEVBQ2pDO0FBQ0Y7QUFRTyxTQUFTLHdCQUF3QixNQUFvQjtBQUMxRCxNQUFJO0FBQ0YsV0FBTyxrQkFBa0IsSUFBSSxHQUFHLEVBQUUsT0FBTyxLQUFLLENBQUM7QUFBQSxFQUNqRCxTQUFTLE9BQWdCO0FBQ3ZCLFFBQUksK0RBQStELE9BQU8sSUFBSSxDQUFDLEtBQUssZ0JBQWdCLEtBQUssQ0FBQyxFQUFFO0FBQUEsRUFDOUc7QUFDRjtBQVFPLFNBQVMsdUJBQXVCLE1BQThDO0FBQ25GLE1BQUk7QUFDSixNQUFJO0FBQ0YsYUFBUyxLQUFLLE1BQU0sYUFBYSxrQkFBa0IsSUFBSSxHQUFHLE9BQU8sQ0FBQztBQUFBLEVBQ3BFLFFBQVE7QUFDTixXQUFPO0FBQUEsRUFDVDtBQUVBLFNBQU8sWUFBWSxRQUFRLElBQUk7QUFDakM7QUFRTyxTQUFTLHdCQUF3QixRQUE2QztBQUNuRixRQUFNLFNBQTZCO0FBQUEsSUFDakMsS0FBSyxPQUFPO0FBQUEsSUFDWixNQUFNLE9BQU87QUFBQSxJQUNiLHlCQUF5QixLQUFLLElBQUk7QUFBQSxFQUNwQztBQUVBLE1BQUk7QUFDRixjQUFVLG1CQUFtQixHQUFHLEVBQUUsV0FBVyxLQUFLLENBQUM7QUFDbkQsa0JBQWMsa0JBQWtCLE9BQU8sSUFBSSxHQUFHLEtBQUssVUFBVSxNQUFNLENBQUM7QUFBQSxFQUN0RSxTQUFTLE9BQWdCO0FBQ3ZCLFFBQUksOERBQThELE9BQU8sT0FBTyxJQUFJLENBQUMsS0FBSyxnQkFBZ0IsS0FBSyxDQUFDLEVBQUU7QUFBQSxFQUNwSDtBQUNGO0FBRUEsU0FBUyxhQUFhLE9BQW9DO0FBQ3hELFNBQU8sT0FBTyxVQUFVLFlBQVksVUFBVSxRQUFRLFVBQVUsUUFBUSxPQUFPLE1BQU0sSUFBSSxJQUFJO0FBQy9GO0FBRUEsU0FBUyxnQkFBZ0IsT0FBd0I7QUFDL0MsU0FBTyxpQkFBaUIsUUFBUSxNQUFNLFVBQVUsT0FBTyxLQUFLO0FBQzlEO0FBRUEsU0FBUyxxQkFBNkI7QUFDcEMsU0FBTyxLQUFLLE9BQU8sR0FBRyxlQUFlO0FBQ3ZDO0FBRUEsU0FBUyxrQkFBa0IsTUFBc0I7QUFDL0MsU0FBTyxLQUFLLG1CQUFtQixHQUFHLEdBQUcsT0FBTyxJQUFJLENBQUMsR0FBRyxrQkFBa0IsRUFBRTtBQUMxRTtBQUVBLFNBQVMsWUFBWSxRQUFpQixNQUE4QztBQUNsRixNQUFJLE9BQU8sV0FBVyxZQUFZLFdBQVcsTUFBTTtBQUNqRCxXQUFPO0FBQUEsRUFDVDtBQUVBLFFBQU0sU0FBUztBQUNmLFFBQU0sRUFBRSxLQUFLLE1BQU0sWUFBWSx3QkFBd0IsSUFBSTtBQUUzRCxNQUFJLE9BQU8sUUFBUSxZQUFZLE9BQU8sNEJBQTRCLFlBQVksZUFBZSxNQUFNO0FBQ2pHLFdBQU87QUFBQSxFQUNUO0FBRUEsU0FBTyxFQUFFLEtBQUssTUFBTSx3QkFBd0I7QUFDOUM7IiwKICAibmFtZXMiOiBbXQp9Cg==
@@ -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>;