obsidian-integration-testing 1.1.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +254 -13
- package/dist/lib/cjs/context-id.cjs +1 -1
- package/dist/lib/cjs/context-id.d.cts +1 -1
- package/dist/lib/cjs/enable-plugin.cjs +54 -0
- package/dist/lib/cjs/enable-plugin.d.cts +44 -0
- package/dist/lib/cjs/exec.cjs +4 -4
- package/dist/lib/cjs/exec.d.cts +8 -8
- package/dist/lib/cjs/function-expression.cjs +1 -1
- package/dist/lib/cjs/function-expression.d.cts +1 -1
- package/dist/lib/cjs/index.cjs +13 -1
- package/dist/lib/cjs/index.d.cts +9 -1
- package/dist/lib/cjs/integration-global-setup.cjs +19 -6
- package/dist/lib/cjs/integration-global-setup.d.cts +1 -6
- package/dist/lib/cjs/json-with-functions.cjs +1 -1
- package/dist/lib/cjs/json-with-functions.d.cts +1 -1
- package/dist/lib/cjs/noop.cjs +1 -1
- package/dist/lib/cjs/noop.d.cts +1 -1
- package/dist/lib/cjs/obsidian-cli.cjs +10 -76
- package/dist/lib/cjs/obsidian-cli.d.cts +9 -3
- package/dist/lib/cjs/obsidian-config.cjs +1 -1
- package/dist/lib/cjs/obsidian-config.d.cts +1 -1
- package/dist/lib/cjs/temp-vault.cjs +47 -5
- package/dist/lib/cjs/temp-vault.d.cts +19 -1
- package/dist/lib/cjs/transport-appium.cjs +232 -0
- package/dist/lib/cjs/transport-appium.d.cts +164 -0
- package/dist/lib/cjs/transport-desktop-cdp.cjs +390 -0
- package/dist/lib/cjs/transport-desktop-cdp.d.cts +158 -0
- package/dist/lib/cjs/transport-desktop-cli.cjs +221 -0
- package/dist/lib/cjs/transport-desktop-cli.d.cts +65 -0
- package/dist/lib/cjs/transport-factory.cjs +94 -0
- package/dist/lib/cjs/transport-factory.d.cts +25 -0
- package/dist/lib/cjs/transport-options.cjs +17 -0
- package/dist/lib/cjs/transport-options.d.cts +100 -0
- package/dist/lib/cjs/transport.cjs +17 -0
- package/dist/lib/cjs/transport.d.cts +86 -0
- package/dist/lib/cjs/type-guards.cjs +1 -1
- package/dist/lib/cjs/type-guards.d.cts +1 -1
- package/dist/lib/cjs/vault-registry.cjs +7 -56
- package/dist/lib/cjs/vault-registry.d.cts +3 -5
- package/dist/lib/esm/context-id.d.mts +1 -1
- package/dist/lib/esm/context-id.mjs +1 -1
- package/dist/lib/esm/enable-plugin.d.mts +44 -0
- package/dist/lib/esm/enable-plugin.mjs +30 -0
- package/dist/lib/esm/exec.d.mts +8 -8
- package/dist/lib/esm/exec.mjs +4 -4
- package/dist/lib/esm/function-expression.d.mts +1 -1
- package/dist/lib/esm/function-expression.mjs +1 -1
- package/dist/lib/esm/index.d.mts +9 -1
- package/dist/lib/esm/index.mjs +9 -1
- package/dist/lib/esm/integration-global-setup.d.mts +1 -6
- package/dist/lib/esm/integration-global-setup.mjs +19 -6
- package/dist/lib/esm/json-with-functions.d.mts +1 -1
- package/dist/lib/esm/json-with-functions.mjs +1 -1
- package/dist/lib/esm/noop.d.mts +1 -1
- package/dist/lib/esm/noop.mjs +1 -1
- package/dist/lib/esm/obsidian-cli.d.mts +9 -3
- package/dist/lib/esm/obsidian-cli.mjs +10 -80
- package/dist/lib/esm/obsidian-config.d.mts +1 -1
- package/dist/lib/esm/obsidian-config.mjs +1 -1
- package/dist/lib/esm/temp-vault.d.mts +19 -1
- package/dist/lib/esm/temp-vault.mjs +54 -7
- package/dist/lib/esm/transport-appium.d.mts +164 -0
- package/dist/lib/esm/transport-appium.mjs +208 -0
- package/dist/lib/esm/transport-desktop-cdp.d.mts +158 -0
- package/dist/lib/esm/transport-desktop-cdp.mjs +356 -0
- package/dist/lib/esm/transport-desktop-cli.d.mts +65 -0
- package/dist/lib/esm/transport-desktop-cli.mjs +190 -0
- package/dist/lib/esm/transport-factory.d.mts +25 -0
- package/dist/lib/esm/transport-factory.mjs +69 -0
- package/dist/lib/esm/transport-options.d.mts +100 -0
- package/dist/lib/esm/transport-options.mjs +1 -0
- package/dist/lib/esm/transport.d.mts +86 -0
- package/dist/lib/esm/transport.mjs +1 -0
- package/dist/lib/esm/type-guards.d.mts +1 -1
- package/dist/lib/esm/type-guards.mjs +1 -1
- package/dist/lib/esm/vault-registry.d.mts +3 -5
- package/dist/lib/esm/vault-registry.mjs +7 -56
- package/dist/obsidian-integration-testing-1.2.0.tgz +0 -0
- package/package.json +16 -2
- package/scripts/postinstall.mjs +29 -0
- package/dist/obsidian-integration-testing-1.1.1.tgz +0 -0
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var transport_desktop_cdp_exports = {};
|
|
30
|
+
__export(transport_desktop_cdp_exports, {
|
|
31
|
+
DesktopCdpTransport: () => DesktopCdpTransport
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(transport_desktop_cdp_exports);
|
|
34
|
+
var import_node_process = __toESM(require("node:process"), 1);
|
|
35
|
+
var import_exec = require("./exec.cjs");
|
|
36
|
+
var import_obsidian_config = require("./obsidian-config.cjs");
|
|
37
|
+
var import_type_guards = require("./type-guards.cjs");
|
|
38
|
+
const CDP_DEFAULT_PORT = 8315;
|
|
39
|
+
const COMMAND_TIMEOUT_IN_MILLISECONDS = 3e4;
|
|
40
|
+
const NO_OUTPUT = "(no output)";
|
|
41
|
+
const VAULT_POLL_INTERVAL_IN_MILLISECONDS = 500;
|
|
42
|
+
const VAULT_POLL_TIMEOUT_IN_MILLISECONDS = 3e4;
|
|
43
|
+
const VAULT_CLOSE_DELAY_IN_MILLISECONDS = 1e3;
|
|
44
|
+
const AUTO_START_POLL_INTERVAL_IN_MILLISECONDS = 2e3;
|
|
45
|
+
const AUTO_START_TIMEOUT_IN_MILLISECONDS = 3e4;
|
|
46
|
+
class DesktopCdpTransport {
|
|
47
|
+
/** */
|
|
48
|
+
isMobile = false;
|
|
49
|
+
activeVaultPath = null;
|
|
50
|
+
cdpPort;
|
|
51
|
+
cdpUrl;
|
|
52
|
+
commandTimeoutInMilliseconds;
|
|
53
|
+
messageId = 0;
|
|
54
|
+
ws = null;
|
|
55
|
+
/**
|
|
56
|
+
* Creates a new CDP transport.
|
|
57
|
+
*
|
|
58
|
+
* @param config - CDP connection configuration.
|
|
59
|
+
*/
|
|
60
|
+
constructor(config) {
|
|
61
|
+
const host = config?.cdpHost ?? "localhost";
|
|
62
|
+
this.cdpPort = config?.cdpPort ?? CDP_DEFAULT_PORT;
|
|
63
|
+
this.cdpUrl = `http://${host}:${String(this.cdpPort)}`;
|
|
64
|
+
this.commandTimeoutInMilliseconds = config?.commandTimeoutInMilliseconds ?? COMMAND_TIMEOUT_IN_MILLISECONDS;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Disposes of the active WebSocket connection.
|
|
68
|
+
*/
|
|
69
|
+
async dispose() {
|
|
70
|
+
this.disconnect();
|
|
71
|
+
await Promise.resolve();
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Evaluates a JavaScript expression inside Obsidian via CDP `Runtime.evaluate`.
|
|
75
|
+
*
|
|
76
|
+
* Routes to the correct vault target based on `options.cwd`.
|
|
77
|
+
*
|
|
78
|
+
* @param expression - The JavaScript expression to evaluate.
|
|
79
|
+
* @param options - Evaluation options.
|
|
80
|
+
* @returns The normalized result string.
|
|
81
|
+
*/
|
|
82
|
+
async evaluate(expression, options) {
|
|
83
|
+
const ws = await this.ensureConnection(options.cwd);
|
|
84
|
+
const response = await this.sendCommand(ws, "Runtime.evaluate", {
|
|
85
|
+
awaitPromise: true,
|
|
86
|
+
expression,
|
|
87
|
+
returnByValue: true
|
|
88
|
+
});
|
|
89
|
+
if (response.result?.exceptionDetails) {
|
|
90
|
+
const desc = response.result.exceptionDetails.exception?.description ?? response.result.exceptionDetails.text;
|
|
91
|
+
throw new Error(`CDP evaluation error: ${desc}`);
|
|
92
|
+
}
|
|
93
|
+
const resultObj = response.result?.result;
|
|
94
|
+
if (!resultObj || resultObj.type === "undefined") {
|
|
95
|
+
return NO_OUTPUT;
|
|
96
|
+
}
|
|
97
|
+
return String(resultObj.value);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Verifies that the CDP endpoint is reachable and has Obsidian targets.
|
|
101
|
+
*
|
|
102
|
+
* If Obsidian is not running, attempts to auto-start it via URI protocol
|
|
103
|
+
* and polls until CDP becomes available.
|
|
104
|
+
*
|
|
105
|
+
* @param vaultPath - The vault path (used for vault registration check).
|
|
106
|
+
*/
|
|
107
|
+
async preflightCheck(vaultPath) {
|
|
108
|
+
if (!(0, import_obsidian_config.isVaultRegistered)(vaultPath)) {
|
|
109
|
+
throw new Error(
|
|
110
|
+
`Vault is not registered in Obsidian: ${vaultPath}. Register the vault first with registerVault() or TempVault.register().`
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
const targets = await this.getPageTargets();
|
|
115
|
+
if (targets.length === 0) {
|
|
116
|
+
throw new Error("No page targets");
|
|
117
|
+
}
|
|
118
|
+
} catch {
|
|
119
|
+
await this.ensureObsidianRunning();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Registers a vault via Electron IPC evaluated through CDP.
|
|
124
|
+
*
|
|
125
|
+
* Uses an existing Obsidian target to send the `vault-open` IPC command,
|
|
126
|
+
* then polls until the new vault's target appears.
|
|
127
|
+
*
|
|
128
|
+
* @param vaultPath - The absolute path to the vault folder.
|
|
129
|
+
*/
|
|
130
|
+
async registerVault(vaultPath) {
|
|
131
|
+
const targets = await this.getPageTargets();
|
|
132
|
+
if (targets.length === 0) {
|
|
133
|
+
throw new Error("No Obsidian CDP targets available. Is Obsidian running?");
|
|
134
|
+
}
|
|
135
|
+
const ipcWs = await this.connectToTarget((0, import_type_guards.ensureNonNullable)(targets[0]));
|
|
136
|
+
try {
|
|
137
|
+
const ipcExpr = buildLayoutReadyExpression(
|
|
138
|
+
`window.electron.ipcRenderer.sendSync('vault-open', ${JSON.stringify(vaultPath)}, false);`
|
|
139
|
+
);
|
|
140
|
+
await this.sendCommand(ipcWs, "Runtime.evaluate", {
|
|
141
|
+
awaitPromise: true,
|
|
142
|
+
expression: ipcExpr,
|
|
143
|
+
returnByValue: true
|
|
144
|
+
});
|
|
145
|
+
} finally {
|
|
146
|
+
ipcWs.close();
|
|
147
|
+
}
|
|
148
|
+
const deadline = Date.now() + VAULT_POLL_TIMEOUT_IN_MILLISECONDS;
|
|
149
|
+
while (Date.now() < deadline) {
|
|
150
|
+
try {
|
|
151
|
+
await this.findTargetForVault(vaultPath);
|
|
152
|
+
return;
|
|
153
|
+
} catch {
|
|
154
|
+
}
|
|
155
|
+
await delay(VAULT_POLL_INTERVAL_IN_MILLISECONDS);
|
|
156
|
+
}
|
|
157
|
+
throw new Error(`Vault at ${vaultPath} did not become ready within ${String(VAULT_POLL_TIMEOUT_IN_MILLISECONDS)}ms`);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Unregisters a vault by destroying its window and removing it from the registry.
|
|
161
|
+
*
|
|
162
|
+
* @param vaultPath - The absolute path to the vault folder.
|
|
163
|
+
*/
|
|
164
|
+
async unregisterVault(vaultPath) {
|
|
165
|
+
try {
|
|
166
|
+
const target = await this.findTargetForVault(vaultPath);
|
|
167
|
+
const ws = await this.connectToTarget(target);
|
|
168
|
+
try {
|
|
169
|
+
const destroyExpr = buildLayoutReadyExpression(`
|
|
170
|
+
setTimeout(() => {
|
|
171
|
+
if (window.electron && window.electron.remote) {
|
|
172
|
+
window.electron.remote.getCurrentWindow().destroy();
|
|
173
|
+
}
|
|
174
|
+
}, 0);
|
|
175
|
+
`);
|
|
176
|
+
await this.sendCommand(ws, "Runtime.evaluate", {
|
|
177
|
+
awaitPromise: true,
|
|
178
|
+
expression: destroyExpr,
|
|
179
|
+
returnByValue: true
|
|
180
|
+
});
|
|
181
|
+
} finally {
|
|
182
|
+
ws.close();
|
|
183
|
+
}
|
|
184
|
+
} catch {
|
|
185
|
+
}
|
|
186
|
+
if (this.activeVaultPath === vaultPath) {
|
|
187
|
+
this.disconnect();
|
|
188
|
+
}
|
|
189
|
+
await delay(VAULT_CLOSE_DELAY_IN_MILLISECONDS);
|
|
190
|
+
const targets = await this.getPageTargets();
|
|
191
|
+
if (targets.length > 0) {
|
|
192
|
+
const ws = await this.connectToTarget((0, import_type_guards.ensureNonNullable)(targets[0]));
|
|
193
|
+
try {
|
|
194
|
+
const removeExpr = buildLayoutReadyExpression(
|
|
195
|
+
`window.electron.ipcRenderer.sendSync('vault-remove', ${JSON.stringify(vaultPath)});`
|
|
196
|
+
);
|
|
197
|
+
await this.sendCommand(ws, "Runtime.evaluate", {
|
|
198
|
+
awaitPromise: true,
|
|
199
|
+
expression: removeExpr,
|
|
200
|
+
returnByValue: true
|
|
201
|
+
});
|
|
202
|
+
} finally {
|
|
203
|
+
ws.close();
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Connects to a CDP target's WebSocket endpoint.
|
|
209
|
+
*
|
|
210
|
+
* @param target - The CDP target to connect to.
|
|
211
|
+
* @returns The open WebSocket connection.
|
|
212
|
+
*/
|
|
213
|
+
async connectToTarget(target) {
|
|
214
|
+
const ws = new WebSocket(target.webSocketDebuggerUrl);
|
|
215
|
+
await new Promise((resolve, reject) => {
|
|
216
|
+
ws.onopen = () => {
|
|
217
|
+
resolve();
|
|
218
|
+
};
|
|
219
|
+
ws.onerror = () => {
|
|
220
|
+
reject(new Error(`Failed to connect to CDP target: ${target.webSocketDebuggerUrl}`));
|
|
221
|
+
};
|
|
222
|
+
});
|
|
223
|
+
return ws;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Disconnects the active WebSocket connection.
|
|
227
|
+
*/
|
|
228
|
+
disconnect() {
|
|
229
|
+
if (this.ws?.readyState === WebSocket.OPEN) {
|
|
230
|
+
this.ws.close();
|
|
231
|
+
}
|
|
232
|
+
this.ws = null;
|
|
233
|
+
this.activeVaultPath = null;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Ensures there is an active WebSocket connection to the correct vault target.
|
|
237
|
+
*
|
|
238
|
+
* Reuses the existing connection if it targets the requested vault.
|
|
239
|
+
* Otherwise, finds the correct target and reconnects.
|
|
240
|
+
*
|
|
241
|
+
* @param vaultPath - The vault path to target.
|
|
242
|
+
* @returns The active WebSocket connection.
|
|
243
|
+
*/
|
|
244
|
+
async ensureConnection(vaultPath) {
|
|
245
|
+
if (this.ws?.readyState === WebSocket.OPEN && this.activeVaultPath === vaultPath) {
|
|
246
|
+
return this.ws;
|
|
247
|
+
}
|
|
248
|
+
this.disconnect();
|
|
249
|
+
const target = await this.findTargetForVault(vaultPath);
|
|
250
|
+
this.ws = await this.connectToTarget(target);
|
|
251
|
+
this.activeVaultPath = vaultPath;
|
|
252
|
+
return this.ws;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Launches Obsidian with `--remote-debugging-port` and polls until CDP becomes available.
|
|
256
|
+
*/
|
|
257
|
+
async ensureObsidianRunning() {
|
|
258
|
+
console.warn("Obsidian CDP not reachable. Starting Obsidian with remote debugging...");
|
|
259
|
+
try {
|
|
260
|
+
await (0, import_exec.exec)(getObsidianLaunchCommand(this.cdpPort), { isQuiet: true });
|
|
261
|
+
} catch {
|
|
262
|
+
}
|
|
263
|
+
const deadline = Date.now() + AUTO_START_TIMEOUT_IN_MILLISECONDS;
|
|
264
|
+
while (Date.now() < deadline) {
|
|
265
|
+
await delay(AUTO_START_POLL_INTERVAL_IN_MILLISECONDS);
|
|
266
|
+
try {
|
|
267
|
+
const targets = await this.getPageTargets();
|
|
268
|
+
if (targets.length > 0) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
} catch {
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
throw new Error(`Obsidian did not start within ${String(AUTO_START_TIMEOUT_IN_MILLISECONDS)}ms. Ensure Obsidian is installed and accessible.`);
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Finds the CDP target that has the given vault open.
|
|
278
|
+
*
|
|
279
|
+
* For a single target, returns it directly. For multiple targets,
|
|
280
|
+
* probes each by evaluating `getBasePath()` to find the match.
|
|
281
|
+
*
|
|
282
|
+
* @param vaultPath - The vault path to match.
|
|
283
|
+
* @returns The matching CDP target.
|
|
284
|
+
*/
|
|
285
|
+
async findTargetForVault(vaultPath) {
|
|
286
|
+
const targets = await this.getPageTargets();
|
|
287
|
+
if (targets.length === 0) {
|
|
288
|
+
throw new Error("No Obsidian CDP targets found");
|
|
289
|
+
}
|
|
290
|
+
if (targets.length === 1) {
|
|
291
|
+
return (0, import_type_guards.ensureNonNullable)(targets[0]);
|
|
292
|
+
}
|
|
293
|
+
for (const target of targets) {
|
|
294
|
+
try {
|
|
295
|
+
const basePath = await this.probeVaultPath(target);
|
|
296
|
+
if (basePath === vaultPath) {
|
|
297
|
+
return target;
|
|
298
|
+
}
|
|
299
|
+
} catch {
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
throw new Error(`No CDP target found for vault: ${vaultPath}`);
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Fetches the list of page-type targets from the CDP `/json` endpoint.
|
|
306
|
+
*
|
|
307
|
+
* @returns The list of page targets.
|
|
308
|
+
*/
|
|
309
|
+
async getPageTargets() {
|
|
310
|
+
const response = await fetch(`${this.cdpUrl}/json`);
|
|
311
|
+
const targets = await response.json();
|
|
312
|
+
return targets.filter((t) => t.type === "page");
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Probes a target to discover which vault path it has open.
|
|
316
|
+
*
|
|
317
|
+
* Creates a temporary WebSocket connection, evaluates `getBasePath()`,
|
|
318
|
+
* and returns the result.
|
|
319
|
+
*
|
|
320
|
+
* @param target - The CDP target to probe.
|
|
321
|
+
* @returns The vault's base path.
|
|
322
|
+
*/
|
|
323
|
+
async probeVaultPath(target) {
|
|
324
|
+
const ws = await this.connectToTarget(target);
|
|
325
|
+
try {
|
|
326
|
+
const response = await this.sendCommand(ws, "Runtime.evaluate", {
|
|
327
|
+
expression: "app.vault.adapter.getBasePath()",
|
|
328
|
+
returnByValue: true
|
|
329
|
+
});
|
|
330
|
+
return String(response.result?.result?.value);
|
|
331
|
+
} finally {
|
|
332
|
+
ws.close();
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Sends a CDP command over WebSocket and waits for the response.
|
|
337
|
+
*
|
|
338
|
+
* @param ws - The WebSocket connection.
|
|
339
|
+
* @param method - The CDP method name.
|
|
340
|
+
* @param params - The CDP method parameters.
|
|
341
|
+
* @returns The CDP response.
|
|
342
|
+
*/
|
|
343
|
+
async sendCommand(ws, method, params) {
|
|
344
|
+
const id = ++this.messageId;
|
|
345
|
+
return new Promise((resolve, reject) => {
|
|
346
|
+
const timeout = setTimeout(() => {
|
|
347
|
+
ws.removeEventListener("message", handler);
|
|
348
|
+
reject(new Error(`CDP command timed out after ${String(this.commandTimeoutInMilliseconds)}ms: ${method}`));
|
|
349
|
+
}, this.commandTimeoutInMilliseconds);
|
|
350
|
+
function handler(event) {
|
|
351
|
+
const msg = JSON.parse(String(event.data));
|
|
352
|
+
if (msg.id === id) {
|
|
353
|
+
clearTimeout(timeout);
|
|
354
|
+
ws.removeEventListener("message", handler);
|
|
355
|
+
resolve(msg);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
ws.addEventListener("message", handler);
|
|
359
|
+
ws.send(JSON.stringify({ id, method, params }));
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
function buildLayoutReadyExpression(body) {
|
|
364
|
+
return `(async () => {
|
|
365
|
+
if (!app.workspace.layoutReady) {
|
|
366
|
+
await new Promise((resolve) => app.workspace.onLayoutReady(resolve));
|
|
367
|
+
}
|
|
368
|
+
${body}
|
|
369
|
+
})()`;
|
|
370
|
+
}
|
|
371
|
+
function delay(ms) {
|
|
372
|
+
return new Promise((resolve) => {
|
|
373
|
+
setTimeout(resolve, ms);
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
function getObsidianLaunchCommand(port) {
|
|
377
|
+
const flag = `--remote-debugging-port=${String(port)}`;
|
|
378
|
+
if (import_node_process.default.platform === "win32") {
|
|
379
|
+
return `start "" "%LOCALAPPDATA%\\Programs\\Obsidian\\Obsidian.exe" ${flag}`;
|
|
380
|
+
}
|
|
381
|
+
if (import_node_process.default.platform === "darwin") {
|
|
382
|
+
return `/Applications/Obsidian.app/Contents/MacOS/Obsidian ${flag} &`;
|
|
383
|
+
}
|
|
384
|
+
return `obsidian ${flag} &`;
|
|
385
|
+
}
|
|
386
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
387
|
+
0 && (module.exports = {
|
|
388
|
+
DesktopCdpTransport
|
|
389
|
+
});
|
|
390
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3RyYW5zcG9ydC1kZXNrdG9wLWNkcC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIERlc2t0b3AgQ0RQIHRyYW5zcG9ydCBcdTIwMTQgZXZhbHVhdGVzIGV4cHJlc3Npb25zIHZpYSBDaHJvbWUgRGV2VG9vbHMgUHJvdG9jb2xcbiAqIG92ZXIgV2ViU29ja2V0IGFuZCBtYW5hZ2VzIHZhdWx0cyB2aWEgRWxlY3Ryb24gSVBDLlxuICpcbiAqIE9ic2lkaWFuIGV4cG9zZXMgQ0RQIG9uIHBvcnQgODMxNSBieSBkZWZhdWx0LiBUaGlzIHRyYW5zcG9ydCBjb25uZWN0cyB0b1xuICogcGFnZSB0YXJnZXRzLCBzZW5kcyBgUnVudGltZS5ldmFsdWF0ZWAgY29tbWFuZHMsIGFuZCByb3V0ZXMgdG8gdGhlIGNvcnJlY3RcbiAqIHZhdWx0IHRhcmdldCB1c2luZyBgZ2V0QmFzZVBhdGgoKWAgcHJvYmluZy5cbiAqXG4gKiBBZHZhbnRhZ2VzIG92ZXIgQ0xJIHRyYW5zcG9ydDpcbiAqIC0gTm8gQ0xJIGJpbmFyeSBpbnN0YWxsYXRpb24gbmVlZGVkXG4gKiAtIE5vIFwiQ0xJIGVuYWJsZWRcIiBzZXR0aW5nIHJlcXVpcmVkIGluIE9ic2lkaWFuXG4gKiAtIExvd2VyIG92ZXJoZWFkIChXZWJTb2NrZXQgdnMuIHByb2Nlc3Mgc3Bhd24gcGVyIGV2YWwpXG4gKlxuICogUmVxdWlyZW1lbnRzOlxuICogLSBPYnNpZGlhbiBtdXN0IGJlIHJ1bm5pbmcgd2l0aCByZW1vdGUgZGVidWdnaW5nIGVuYWJsZWQgKHBvcnQgODMxNSlcbiAqIC0gTm9kZS5qcyAyMisgKHVzZXMgYnVpbHQtaW4gYFdlYlNvY2tldGAgYW5kIGBmZXRjaGAgZ2xvYmFscylcbiAqL1xuXG4vKiB2OCBpZ25vcmUgc3RhcnQgLS0gSW50ZWdyYXRpb24tdGltZSBjb2RlIGNvdmVyZWQgYnkgaW50ZWdyYXRpb24gdGVzdHMsIG5vdCB1bml0IHRlc3RzLiAqL1xuXG5pbXBvcnQgcHJvY2VzcyBmcm9tICdub2RlOnByb2Nlc3MnO1xuXG5pbXBvcnQgdHlwZSB7XG4gIE9ic2lkaWFuVHJhbnNwb3J0LFxuICBUcmFuc3BvcnRFdmFsT3B0aW9uc1xufSBmcm9tICcuL3RyYW5zcG9ydC5janMnO1xuXG5pbXBvcnQgeyBleGVjIH0gZnJvbSAnLi9leGVjLmNqcyc7XG5pbXBvcnQgeyBpc1ZhdWx0UmVnaXN0ZXJlZCB9IGZyb20gJy4vb2JzaWRpYW4tY29uZmlnLmNqcyc7XG5pbXBvcnQgeyBlbnN1cmVOb25OdWxsYWJsZSB9IGZyb20gJy4vdHlwZS1ndWFyZHMuY2pzJztcblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIGZvciB0aGUgQ0RQIHRyYW5zcG9ydC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZXNrdG9wQ2RwVHJhbnNwb3J0Q29uZmlnIHtcbiAgLyoqXG4gICAqIENEUCBob3N0LiBEZWZhdWx0cyB0byBgJ2xvY2FsaG9zdCdgLlxuICAgKi9cbiAgY2RwSG9zdD86IHN0cmluZztcblxuICAvKipcbiAgICogQ0RQIHBvcnQuIERlZmF1bHRzIHRvIGA4MzE1YC5cbiAgICovXG4gIGNkcFBvcnQ/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRpbWVvdXQgaW4gbWlsbGlzZWNvbmRzIGZvciBpbmRpdmlkdWFsIENEUCBjb21tYW5kcy5cbiAgICogRGVmYXVsdHMgdG8gYDMwMDAwYC5cbiAgICovXG4gIGNvbW1hbmRUaW1lb3V0SW5NaWxsaXNlY29uZHM/OiBudW1iZXI7XG59XG5cbmludGVyZmFjZSBDZHBFeGNlcHRpb25EZXRhaWxzIHtcbiAgZXhjZXB0aW9uPzogQ2RwRXhjZXB0aW9uT2JqZWN0O1xuICB0ZXh0OiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBDZHBFeGNlcHRpb25PYmplY3Qge1xuICBkZXNjcmlwdGlvbj86IHN0cmluZztcbn1cblxuaW50ZXJmYWNlIENkcFJlc3BvbnNlIHtcbiAgaWQ6IG51bWJlcjtcbiAgcmVzdWx0PzogQ2RwUmVzcG9uc2VSZXN1bHQ7XG59XG5cbmludGVyZmFjZSBDZHBSZXNwb25zZVJlc3VsdCB7XG4gIGV4Y2VwdGlvbkRldGFpbHM/OiBDZHBFeGNlcHRpb25EZXRhaWxzO1xuICByZXN1bHQ/OiBDZHBWYWx1ZTtcbn1cblxuaW50ZXJmYWNlIENkcFRhcmdldCB7XG4gIGlkOiBzdHJpbmc7XG4gIHRpdGxlOiBzdHJpbmc7XG4gIHR5cGU6IHN0cmluZztcbiAgdXJsOiBzdHJpbmc7XG4gIHdlYlNvY2tldERlYnVnZ2VyVXJsOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBDZHBWYWx1ZSB7XG4gIHR5cGU6IHN0cmluZztcbiAgdmFsdWU/OiB1bmtub3duO1xufVxuXG5jb25zdCBDRFBfREVGQVVMVF9QT1JUID0gODMxNTtcbmNvbnN0IENPTU1BTkRfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMgPSAzMDAwMDtcbmNvbnN0IE5PX09VVFBVVCA9ICcobm8gb3V0cHV0KSc7XG5jb25zdCBWQVVMVF9QT0xMX0lOVEVSVkFMX0lOX01JTExJU0VDT05EUyA9IDUwMDtcbmNvbnN0IFZBVUxUX1BPTExfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMgPSAzMDAwMDtcbmNvbnN0IFZBVUxUX0NMT1NFX0RFTEFZX0lOX01JTExJU0VDT05EUyA9IDEwMDA7XG5jb25zdCBBVVRPX1NUQVJUX1BPTExfSU5URVJWQUxfSU5fTUlMTElTRUNPTkRTID0gMjAwMDtcbmNvbnN0IEFVVE9fU1RBUlRfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMgPSAzMDAwMDtcblxuLyoqXG4gKiBUcmFuc3BvcnQgdGhhdCBjb21tdW5pY2F0ZXMgd2l0aCBEZXNrdG9wIE9ic2lkaWFuIHZpYSBDaHJvbWUgRGV2VG9vbHMgUHJvdG9jb2wuXG4gKlxuICogQ29ubmVjdHMgdG8gT2JzaWRpYW4ncyBDRFAgV2ViU29ja2V0IGVuZHBvaW50LCBzZW5kcyBgUnVudGltZS5ldmFsdWF0ZWBcbiAqIGNvbW1hbmRzLCBhbmQgcm91dGVzIGV4cHJlc3Npb25zIHRvIHRoZSBjb3JyZWN0IHZhdWx0IHRhcmdldC5cbiAqL1xuZXhwb3J0IGNsYXNzIERlc2t0b3BDZHBUcmFuc3BvcnQgaW1wbGVtZW50cyBPYnNpZGlhblRyYW5zcG9ydCB7XG4gIC8qKiAqL1xuICBwdWJsaWMgcmVhZG9ubHkgaXNNb2JpbGUgPSBmYWxzZTtcbiAgcHJpdmF0ZSBhY3RpdmVWYXVsdFBhdGg6IG51bGwgfCBzdHJpbmcgPSBudWxsO1xuICBwcml2YXRlIHJlYWRvbmx5IGNkcFBvcnQ6IG51bWJlcjtcbiAgcHJpdmF0ZSByZWFkb25seSBjZHBVcmw6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBjb21tYW5kVGltZW91dEluTWlsbGlzZWNvbmRzOiBudW1iZXI7XG4gIHByaXZhdGUgbWVzc2FnZUlkID0gMDtcbiAgcHJpdmF0ZSB3czogbnVsbCB8IFdlYlNvY2tldCA9IG51bGw7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgQ0RQIHRyYW5zcG9ydC5cbiAgICpcbiAgICogQHBhcmFtIGNvbmZpZyAtIENEUCBjb25uZWN0aW9uIGNvbmZpZ3VyYXRpb24uXG4gICAqL1xuICBwdWJsaWMgY29uc3RydWN0b3IoY29uZmlnPzogRGVza3RvcENkcFRyYW5zcG9ydENvbmZpZykge1xuICAgIGNvbnN0IGhvc3QgPSBjb25maWc/LmNkcEhvc3QgPz8gJ2xvY2FsaG9zdCc7XG4gICAgdGhpcy5jZHBQb3J0ID0gY29uZmlnPy5jZHBQb3J0ID8/IENEUF9ERUZBVUxUX1BPUlQ7XG4gICAgdGhpcy5jZHBVcmwgPSBgaHR0cDovLyR7aG9zdH06JHtTdHJpbmcodGhpcy5jZHBQb3J0KX1gO1xuICAgIHRoaXMuY29tbWFuZFRpbWVvdXRJbk1pbGxpc2Vjb25kcyA9IGNvbmZpZz8uY29tbWFuZFRpbWVvdXRJbk1pbGxpc2Vjb25kcyA/PyBDT01NQU5EX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTO1xuICB9XG5cbiAgLyoqXG4gICAqIERpc3Bvc2VzIG9mIHRoZSBhY3RpdmUgV2ViU29ja2V0IGNvbm5lY3Rpb24uXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgZGlzcG9zZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLmRpc2Nvbm5lY3QoKTtcbiAgICBhd2FpdCBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFdmFsdWF0ZXMgYSBKYXZhU2NyaXB0IGV4cHJlc3Npb24gaW5zaWRlIE9ic2lkaWFuIHZpYSBDRFAgYFJ1bnRpbWUuZXZhbHVhdGVgLlxuICAgKlxuICAgKiBSb3V0ZXMgdG8gdGhlIGNvcnJlY3QgdmF1bHQgdGFyZ2V0IGJhc2VkIG9uIGBvcHRpb25zLmN3ZGAuXG4gICAqXG4gICAqIEBwYXJhbSBleHByZXNzaW9uIC0gVGhlIEphdmFTY3JpcHQgZXhwcmVzc2lvbiB0byBldmFsdWF0ZS5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBFdmFsdWF0aW9uIG9wdGlvbnMuXG4gICAqIEByZXR1cm5zIFRoZSBub3JtYWxpemVkIHJlc3VsdCBzdHJpbmcuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgZXZhbHVhdGUoZXhwcmVzc2lvbjogc3RyaW5nLCBvcHRpb25zOiBUcmFuc3BvcnRFdmFsT3B0aW9ucyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3Qgd3MgPSBhd2FpdCB0aGlzLmVuc3VyZUNvbm5lY3Rpb24ob3B0aW9ucy5jd2QpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5zZW5kQ29tbWFuZCh3cywgJ1J1bnRpbWUuZXZhbHVhdGUnLCB7XG4gICAgICBhd2FpdFByb21pc2U6IHRydWUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgcmV0dXJuQnlWYWx1ZTogdHJ1ZVxuICAgIH0pO1xuXG4gICAgaWYgKHJlc3BvbnNlLnJlc3VsdD8uZXhjZXB0aW9uRGV0YWlscykge1xuICAgICAgY29uc3QgZGVzYyA9IHJlc3BvbnNlLnJlc3VsdC5leGNlcHRpb25EZXRhaWxzLmV4Y2VwdGlvbj8uZGVzY3JpcHRpb25cbiAgICAgICAgPz8gcmVzcG9uc2UucmVzdWx0LmV4Y2VwdGlvbkRldGFpbHMudGV4dDtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ0RQIGV2YWx1YXRpb24gZXJyb3I6ICR7ZGVzY31gKTtcbiAgICB9XG5cbiAgICBjb25zdCByZXN1bHRPYmogPSByZXNwb25zZS5yZXN1bHQ/LnJlc3VsdDtcbiAgICBpZiAoIXJlc3VsdE9iaiB8fCByZXN1bHRPYmoudHlwZSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVybiBOT19PVVRQVVQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIFN0cmluZyhyZXN1bHRPYmoudmFsdWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFZlcmlmaWVzIHRoYXQgdGhlIENEUCBlbmRwb2ludCBpcyByZWFjaGFibGUgYW5kIGhhcyBPYnNpZGlhbiB0YXJnZXRzLlxuICAgKlxuICAgKiBJZiBPYnNpZGlhbiBpcyBub3QgcnVubmluZywgYXR0ZW1wdHMgdG8gYXV0by1zdGFydCBpdCB2aWEgVVJJIHByb3RvY29sXG4gICAqIGFuZCBwb2xscyB1bnRpbCBDRFAgYmVjb21lcyBhdmFpbGFibGUuXG4gICAqXG4gICAqIEBwYXJhbSB2YXVsdFBhdGggLSBUaGUgdmF1bHQgcGF0aCAodXNlZCBmb3IgdmF1bHQgcmVnaXN0cmF0aW9uIGNoZWNrKS5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBwcmVmbGlnaHRDaGVjayh2YXVsdFBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghaXNWYXVsdFJlZ2lzdGVyZWQodmF1bHRQYXRoKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgVmF1bHQgaXMgbm90IHJlZ2lzdGVyZWQgaW4gT2JzaWRpYW46ICR7dmF1bHRQYXRofS4gUmVnaXN0ZXIgdGhlIHZhdWx0IGZpcnN0IHdpdGggcmVnaXN0ZXJWYXVsdCgpIG9yIFRlbXBWYXVsdC5yZWdpc3RlcigpLmBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHRhcmdldHMgPSBhd2FpdCB0aGlzLmdldFBhZ2VUYXJnZXRzKCk7XG4gICAgICBpZiAodGFyZ2V0cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBwYWdlIHRhcmdldHMnKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIHtcbiAgICAgIGF3YWl0IHRoaXMuZW5zdXJlT2JzaWRpYW5SdW5uaW5nKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyBhIHZhdWx0IHZpYSBFbGVjdHJvbiBJUEMgZXZhbHVhdGVkIHRocm91Z2ggQ0RQLlxuICAgKlxuICAgKiBVc2VzIGFuIGV4aXN0aW5nIE9ic2lkaWFuIHRhcmdldCB0byBzZW5kIHRoZSBgdmF1bHQtb3BlbmAgSVBDIGNvbW1hbmQsXG4gICAqIHRoZW4gcG9sbHMgdW50aWwgdGhlIG5ldyB2YXVsdCdzIHRhcmdldCBhcHBlYXJzLlxuICAgKlxuICAgKiBAcGFyYW0gdmF1bHRQYXRoIC0gVGhlIGFic29sdXRlIHBhdGggdG8gdGhlIHZhdWx0IGZvbGRlci5cbiAgICovXG4gIHB1YmxpYyBhc3luYyByZWdpc3RlclZhdWx0KHZhdWx0UGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgdGFyZ2V0cyA9IGF3YWl0IHRoaXMuZ2V0UGFnZVRhcmdldHMoKTtcbiAgICBpZiAodGFyZ2V0cy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTm8gT2JzaWRpYW4gQ0RQIHRhcmdldHMgYXZhaWxhYmxlLiBJcyBPYnNpZGlhbiBydW5uaW5nPycpO1xuICAgIH1cblxuICAgIGNvbnN0IGlwY1dzID0gYXdhaXQgdGhpcy5jb25uZWN0VG9UYXJnZXQoZW5zdXJlTm9uTnVsbGFibGUodGFyZ2V0c1swXSkpO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBpcGNFeHByID0gYnVpbGRMYXlvdXRSZWFkeUV4cHJlc3Npb24oXG4gICAgICAgIGB3aW5kb3cuZWxlY3Ryb24uaXBjUmVuZGVyZXIuc2VuZFN5bmMoJ3ZhdWx0LW9wZW4nLCAke0pTT04uc3RyaW5naWZ5KHZhdWx0UGF0aCl9LCBmYWxzZSk7YFxuICAgICAgKTtcbiAgICAgIGF3YWl0IHRoaXMuc2VuZENvbW1hbmQoaXBjV3MsICdSdW50aW1lLmV2YWx1YXRlJywge1xuICAgICAgICBhd2FpdFByb21pc2U6IHRydWUsXG4gICAgICAgIGV4cHJlc3Npb246IGlwY0V4cHIsXG4gICAgICAgIHJldHVybkJ5VmFsdWU6IHRydWVcbiAgICAgIH0pO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBpcGNXcy5jbG9zZSgpO1xuICAgIH1cblxuICAgIGNvbnN0IGRlYWRsaW5lID0gRGF0ZS5ub3coKSArIFZBVUxUX1BPTExfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFM7XG4gICAgd2hpbGUgKERhdGUubm93KCkgPCBkZWFkbGluZSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgdGhpcy5maW5kVGFyZ2V0Rm9yVmF1bHQodmF1bHRQYXRoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIFZhdWx0IHRhcmdldCBub3QgcmVhZHkgeWV0LlxuICAgICAgfVxuICAgICAgYXdhaXQgZGVsYXkoVkFVTFRfUE9MTF9JTlRFUlZBTF9JTl9NSUxMSVNFQ09ORFMpO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoYFZhdWx0IGF0ICR7dmF1bHRQYXRofSBkaWQgbm90IGJlY29tZSByZWFkeSB3aXRoaW4gJHtTdHJpbmcoVkFVTFRfUE9MTF9USU1FT1VUX0lOX01JTExJU0VDT05EUyl9bXNgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVbnJlZ2lzdGVycyBhIHZhdWx0IGJ5IGRlc3Ryb3lpbmcgaXRzIHdpbmRvdyBhbmQgcmVtb3ZpbmcgaXQgZnJvbSB0aGUgcmVnaXN0cnkuXG4gICAqXG4gICAqIEBwYXJhbSB2YXVsdFBhdGggLSBUaGUgYWJzb2x1dGUgcGF0aCB0byB0aGUgdmF1bHQgZm9sZGVyLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIHVucmVnaXN0ZXJWYXVsdCh2YXVsdFBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB0YXJnZXQgPSBhd2FpdCB0aGlzLmZpbmRUYXJnZXRGb3JWYXVsdCh2YXVsdFBhdGgpO1xuICAgICAgY29uc3Qgd3MgPSBhd2FpdCB0aGlzLmNvbm5lY3RUb1RhcmdldCh0YXJnZXQpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgZGVzdHJveUV4cHIgPSBidWlsZExheW91dFJlYWR5RXhwcmVzc2lvbihgXG4gICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICBpZiAod2luZG93LmVsZWN0cm9uICYmIHdpbmRvdy5lbGVjdHJvbi5yZW1vdGUpIHtcbiAgICAgICAgICAgICAgd2luZG93LmVsZWN0cm9uLnJlbW90ZS5nZXRDdXJyZW50V2luZG93KCkuZGVzdHJveSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sIDApO1xuICAgICAgICBgKTtcbiAgICAgICAgYXdhaXQgdGhpcy5zZW5kQ29tbWFuZCh3cywgJ1J1bnRpbWUuZXZhbHVhdGUnLCB7XG4gICAgICAgICAgYXdhaXRQcm9taXNlOiB0cnVlLFxuICAgICAgICAgIGV4cHJlc3Npb246IGRlc3Ryb3lFeHByLFxuICAgICAgICAgIHJldHVybkJ5VmFsdWU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICB3cy5jbG9zZSgpO1xuICAgICAgfVxuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gV2luZG93IG1heSBhbHJlYWR5IGJlIGNsb3NlZC5cbiAgICB9XG5cbiAgICBpZiAodGhpcy5hY3RpdmVWYXVsdFBhdGggPT09IHZhdWx0UGF0aCkge1xuICAgICAgdGhpcy5kaXNjb25uZWN0KCk7XG4gICAgfVxuXG4gICAgYXdhaXQgZGVsYXkoVkFVTFRfQ0xPU0VfREVMQVlfSU5fTUlMTElTRUNPTkRTKTtcblxuICAgIGNvbnN0IHRhcmdldHMgPSBhd2FpdCB0aGlzLmdldFBhZ2VUYXJnZXRzKCk7XG4gICAgaWYgKHRhcmdldHMubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3Qgd3MgPSBhd2FpdCB0aGlzLmNvbm5lY3RUb1RhcmdldChlbnN1cmVOb25OdWxsYWJsZSh0YXJnZXRzWzBdKSk7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZW1vdmVFeHByID0gYnVpbGRMYXlvdXRSZWFkeUV4cHJlc3Npb24oXG4gICAgICAgICAgYHdpbmRvdy5lbGVjdHJvbi5pcGNSZW5kZXJlci5zZW5kU3luYygndmF1bHQtcmVtb3ZlJywgJHtKU09OLnN0cmluZ2lmeSh2YXVsdFBhdGgpfSk7YFxuICAgICAgICApO1xuICAgICAgICBhd2FpdCB0aGlzLnNlbmRDb21tYW5kKHdzLCAnUnVudGltZS5ldmFsdWF0ZScsIHtcbiAgICAgICAgICBhd2FpdFByb21pc2U6IHRydWUsXG4gICAgICAgICAgZXhwcmVzc2lvbjogcmVtb3ZlRXhwcixcbiAgICAgICAgICByZXR1cm5CeVZhbHVlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgd3MuY2xvc2UoKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ29ubmVjdHMgdG8gYSBDRFAgdGFyZ2V0J3MgV2ViU29ja2V0IGVuZHBvaW50LlxuICAgKlxuICAgKiBAcGFyYW0gdGFyZ2V0IC0gVGhlIENEUCB0YXJnZXQgdG8gY29ubmVjdCB0by5cbiAgICogQHJldHVybnMgVGhlIG9wZW4gV2ViU29ja2V0IGNvbm5lY3Rpb24uXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGNvbm5lY3RUb1RhcmdldCh0YXJnZXQ6IENkcFRhcmdldCk6IFByb21pc2U8V2ViU29ja2V0PiB7XG4gICAgY29uc3Qgd3MgPSBuZXcgV2ViU29ja2V0KHRhcmdldC53ZWJTb2NrZXREZWJ1Z2dlclVybCk7XG4gICAgYXdhaXQgbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgd3Mub25vcGVuID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICByZXNvbHZlKCk7XG4gICAgICB9O1xuICAgICAgd3Mub25lcnJvciA9ICgpOiB2b2lkID0+IHtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgRmFpbGVkIHRvIGNvbm5lY3QgdG8gQ0RQIHRhcmdldDogJHt0YXJnZXQud2ViU29ja2V0RGVidWdnZXJVcmx9YCkpO1xuICAgICAgfTtcbiAgICB9KTtcbiAgICByZXR1cm4gd3M7XG4gIH1cblxuICAvKipcbiAgICogRGlzY29ubmVjdHMgdGhlIGFjdGl2ZSBXZWJTb2NrZXQgY29ubmVjdGlvbi5cbiAgICovXG4gIHByaXZhdGUgZGlzY29ubmVjdCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy53cz8ucmVhZHlTdGF0ZSA9PT0gV2ViU29ja2V0Lk9QRU4pIHtcbiAgICAgIHRoaXMud3MuY2xvc2UoKTtcbiAgICB9XG4gICAgdGhpcy53cyA9IG51bGw7XG4gICAgdGhpcy5hY3RpdmVWYXVsdFBhdGggPSBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIEVuc3VyZXMgdGhlcmUgaXMgYW4gYWN0aXZlIFdlYlNvY2tldCBjb25uZWN0aW9uIHRvIHRoZSBjb3JyZWN0IHZhdWx0IHRhcmdldC5cbiAgICpcbiAgICogUmV1c2VzIHRoZSBleGlzdGluZyBjb25uZWN0aW9uIGlmIGl0IHRhcmdldHMgdGhlIHJlcXVlc3RlZCB2YXVsdC5cbiAgICogT3RoZXJ3aXNlLCBmaW5kcyB0aGUgY29ycmVjdCB0YXJnZXQgYW5kIHJlY29ubmVjdHMuXG4gICAqXG4gICAqIEBwYXJhbSB2YXVsdFBhdGggLSBUaGUgdmF1bHQgcGF0aCB0byB0YXJnZXQuXG4gICAqIEByZXR1cm5zIFRoZSBhY3RpdmUgV2ViU29ja2V0IGNvbm5lY3Rpb24uXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGVuc3VyZUNvbm5lY3Rpb24odmF1bHRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPFdlYlNvY2tldD4ge1xuICAgIGlmICh0aGlzLndzPy5yZWFkeVN0YXRlID09PSBXZWJTb2NrZXQuT1BFTiAmJiB0aGlzLmFjdGl2ZVZhdWx0UGF0aCA9PT0gdmF1bHRQYXRoKSB7XG4gICAgICByZXR1cm4gdGhpcy53cztcbiAgICB9XG5cbiAgICB0aGlzLmRpc2Nvbm5lY3QoKTtcblxuICAgIGNvbnN0IHRhcmdldCA9IGF3YWl0IHRoaXMuZmluZFRhcmdldEZvclZhdWx0KHZhdWx0UGF0aCk7XG4gICAgdGhpcy53cyA9IGF3YWl0IHRoaXMuY29ubmVjdFRvVGFyZ2V0KHRhcmdldCk7XG4gICAgdGhpcy5hY3RpdmVWYXVsdFBhdGggPSB2YXVsdFBhdGg7XG4gICAgcmV0dXJuIHRoaXMud3M7XG4gIH1cblxuICAvKipcbiAgICogTGF1bmNoZXMgT2JzaWRpYW4gd2l0aCBgLS1yZW1vdGUtZGVidWdnaW5nLXBvcnRgIGFuZCBwb2xscyB1bnRpbCBDRFAgYmVjb21lcyBhdmFpbGFibGUuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGVuc3VyZU9ic2lkaWFuUnVubmluZygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zb2xlLndhcm4oJ09ic2lkaWFuIENEUCBub3QgcmVhY2hhYmxlLiBTdGFydGluZyBPYnNpZGlhbiB3aXRoIHJlbW90ZSBkZWJ1Z2dpbmcuLi4nKTtcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCBleGVjKGdldE9ic2lkaWFuTGF1bmNoQ29tbWFuZCh0aGlzLmNkcFBvcnQpLCB7IGlzUXVpZXQ6IHRydWUgfSk7XG4gICAgfSBjYXRjaCB7XG4gICAgICAvLyBUaGUgbGF1bmNoIGNvbW1hbmQgbWF5IGZhaWwgb24gc29tZSBzeXN0ZW1zIFx1MjAxNCB3ZSdsbCBzdGlsbCB0cnkgcG9sbGluZy5cbiAgICB9XG5cbiAgICBjb25zdCBkZWFkbGluZSA9IERhdGUubm93KCkgKyBBVVRPX1NUQVJUX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTO1xuICAgIHdoaWxlIChEYXRlLm5vdygpIDwgZGVhZGxpbmUpIHtcbiAgICAgIGF3YWl0IGRlbGF5KEFVVE9fU1RBUlRfUE9MTF9JTlRFUlZBTF9JTl9NSUxMSVNFQ09ORFMpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgdGFyZ2V0cyA9IGF3YWl0IHRoaXMuZ2V0UGFnZVRhcmdldHMoKTtcbiAgICAgICAgaWYgKHRhcmdldHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIE5vdCByZWFkeSB5ZXQuXG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKGBPYnNpZGlhbiBkaWQgbm90IHN0YXJ0IHdpdGhpbiAke1N0cmluZyhBVVRPX1NUQVJUX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTKX1tcy4gRW5zdXJlIE9ic2lkaWFuIGlzIGluc3RhbGxlZCBhbmQgYWNjZXNzaWJsZS5gKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kcyB0aGUgQ0RQIHRhcmdldCB0aGF0IGhhcyB0aGUgZ2l2ZW4gdmF1bHQgb3Blbi5cbiAgICpcbiAgICogRm9yIGEgc2luZ2xlIHRhcmdldCwgcmV0dXJucyBpdCBkaXJlY3RseS4gRm9yIG11bHRpcGxlIHRhcmdldHMsXG4gICAqIHByb2JlcyBlYWNoIGJ5IGV2YWx1YXRpbmcgYGdldEJhc2VQYXRoKClgIHRvIGZpbmQgdGhlIG1hdGNoLlxuICAgKlxuICAgKiBAcGFyYW0gdmF1bHRQYXRoIC0gVGhlIHZhdWx0IHBhdGggdG8gbWF0Y2guXG4gICAqIEByZXR1cm5zIFRoZSBtYXRjaGluZyBDRFAgdGFyZ2V0LlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBmaW5kVGFyZ2V0Rm9yVmF1bHQodmF1bHRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPENkcFRhcmdldD4ge1xuICAgIGNvbnN0IHRhcmdldHMgPSBhd2FpdCB0aGlzLmdldFBhZ2VUYXJnZXRzKCk7XG5cbiAgICBpZiAodGFyZ2V0cy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTm8gT2JzaWRpYW4gQ0RQIHRhcmdldHMgZm91bmQnKTtcbiAgICB9XG5cbiAgICBpZiAodGFyZ2V0cy5sZW5ndGggPT09IDEpIHtcbiAgICAgIHJldHVybiBlbnN1cmVOb25OdWxsYWJsZSh0YXJnZXRzWzBdKTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHRhcmdldCBvZiB0YXJnZXRzKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBiYXNlUGF0aCA9IGF3YWl0IHRoaXMucHJvYmVWYXVsdFBhdGgodGFyZ2V0KTtcbiAgICAgICAgaWYgKGJhc2VQYXRoID09PSB2YXVsdFBhdGgpIHtcbiAgICAgICAgICByZXR1cm4gdGFyZ2V0O1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLy8gTm90IGEgdmF1bHQgdGFyZ2V0IG9yIG5vdCByZWFkeS5cbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIENEUCB0YXJnZXQgZm91bmQgZm9yIHZhdWx0OiAke3ZhdWx0UGF0aH1gKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGZXRjaGVzIHRoZSBsaXN0IG9mIHBhZ2UtdHlwZSB0YXJnZXRzIGZyb20gdGhlIENEUCBgL2pzb25gIGVuZHBvaW50LlxuICAgKlxuICAgKiBAcmV0dXJucyBUaGUgbGlzdCBvZiBwYWdlIHRhcmdldHMuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGdldFBhZ2VUYXJnZXRzKCk6IFByb21pc2U8Q2RwVGFyZ2V0W10+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKGAke3RoaXMuY2RwVXJsfS9qc29uYCk7XG4gICAgY29uc3QgdGFyZ2V0cyA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKSBhcyBDZHBUYXJnZXRbXTtcbiAgICByZXR1cm4gdGFyZ2V0cy5maWx0ZXIoKHQpID0+IHQudHlwZSA9PT0gJ3BhZ2UnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcm9iZXMgYSB0YXJnZXQgdG8gZGlzY292ZXIgd2hpY2ggdmF1bHQgcGF0aCBpdCBoYXMgb3Blbi5cbiAgICpcbiAgICogQ3JlYXRlcyBhIHRlbXBvcmFyeSBXZWJTb2NrZXQgY29ubmVjdGlvbiwgZXZhbHVhdGVzIGBnZXRCYXNlUGF0aCgpYCxcbiAgICogYW5kIHJldHVybnMgdGhlIHJlc3VsdC5cbiAgICpcbiAgICogQHBhcmFtIHRhcmdldCAtIFRoZSBDRFAgdGFyZ2V0IHRvIHByb2JlLlxuICAgKiBAcmV0dXJucyBUaGUgdmF1bHQncyBiYXNlIHBhdGguXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHByb2JlVmF1bHRQYXRoKHRhcmdldDogQ2RwVGFyZ2V0KTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCB3cyA9IGF3YWl0IHRoaXMuY29ubmVjdFRvVGFyZ2V0KHRhcmdldCk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5zZW5kQ29tbWFuZCh3cywgJ1J1bnRpbWUuZXZhbHVhdGUnLCB7XG4gICAgICAgIGV4cHJlc3Npb246ICdhcHAudmF1bHQuYWRhcHRlci5nZXRCYXNlUGF0aCgpJyxcbiAgICAgICAgcmV0dXJuQnlWYWx1ZTogdHJ1ZVxuICAgICAgfSk7XG4gICAgICByZXR1cm4gU3RyaW5nKHJlc3BvbnNlLnJlc3VsdD8ucmVzdWx0Py52YWx1ZSk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHdzLmNsb3NlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNlbmRzIGEgQ0RQIGNvbW1hbmQgb3ZlciBXZWJTb2NrZXQgYW5kIHdhaXRzIGZvciB0aGUgcmVzcG9uc2UuXG4gICAqXG4gICAqIEBwYXJhbSB3cyAtIFRoZSBXZWJTb2NrZXQgY29ubmVjdGlvbi5cbiAgICogQHBhcmFtIG1ldGhvZCAtIFRoZSBDRFAgbWV0aG9kIG5hbWUuXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBUaGUgQ0RQIG1ldGhvZCBwYXJhbWV0ZXJzLlxuICAgKiBAcmV0dXJucyBUaGUgQ0RQIHJlc3BvbnNlLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBzZW5kQ29tbWFuZCh3czogV2ViU29ja2V0LCBtZXRob2Q6IHN0cmluZywgcGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IFByb21pc2U8Q2RwUmVzcG9uc2U+IHtcbiAgICBjb25zdCBpZCA9ICsrdGhpcy5tZXNzYWdlSWQ7XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2U8Q2RwUmVzcG9uc2U+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IHRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgd3MucmVtb3ZlRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIGhhbmRsZXIpO1xuICAgICAgICByZWplY3QobmV3IEVycm9yKGBDRFAgY29tbWFuZCB0aW1lZCBvdXQgYWZ0ZXIgJHtTdHJpbmcodGhpcy5jb21tYW5kVGltZW91dEluTWlsbGlzZWNvbmRzKX1tczogJHttZXRob2R9YCkpO1xuICAgICAgfSwgdGhpcy5jb21tYW5kVGltZW91dEluTWlsbGlzZWNvbmRzKTtcblxuICAgICAgZnVuY3Rpb24gaGFuZGxlcihldmVudDogTWVzc2FnZUV2ZW50KTogdm9pZCB7XG4gICAgICAgIGNvbnN0IG1zZyA9IEpTT04ucGFyc2UoU3RyaW5nKGV2ZW50LmRhdGEpKSBhcyBDZHBSZXNwb25zZTtcbiAgICAgICAgaWYgKG1zZy5pZCA9PT0gaWQpIHtcbiAgICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICAgICAgd3MucmVtb3ZlRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIGhhbmRsZXIpO1xuICAgICAgICAgIHJlc29sdmUobXNnKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB3cy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgaGFuZGxlcik7XG4gICAgICB3cy5zZW5kKEpTT04uc3RyaW5naWZ5KHsgaWQsIG1ldGhvZCwgcGFyYW1zIH0pKTtcbiAgICB9KTtcbiAgfVxufVxuXG4vKipcbiAqIEJ1aWxkcyBhbiBhc3luYyBJSUZFIHRoYXQgd2FpdHMgZm9yIGxheW91dCByZWFkeSBhbmQgZXhlY3V0ZXMgYSBib2R5LlxuICpcbiAqIEBwYXJhbSBib2R5IC0gVGhlIEphdmFTY3JpcHQgc3RhdGVtZW50cyB0byBleGVjdXRlLlxuICogQHJldHVybnMgVGhlIElJRkUgZXhwcmVzc2lvbiBzdHJpbmcuXG4gKi9cbmZ1bmN0aW9uIGJ1aWxkTGF5b3V0UmVhZHlFeHByZXNzaW9uKGJvZHk6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgKGFzeW5jICgpID0+IHtcbiAgaWYgKCFhcHAud29ya3NwYWNlLmxheW91dFJlYWR5KSB7XG4gICAgYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUpID0+IGFwcC53b3Jrc3BhY2Uub25MYXlvdXRSZWFkeShyZXNvbHZlKSk7XG4gIH1cbiAgJHtib2R5fVxufSkoKWA7XG59XG5cbi8qKlxuICogUmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyBhZnRlciB0aGUgZ2l2ZW4gZGVsYXkuXG4gKlxuICogQHBhcmFtIG1zIC0gVGhlIGRlbGF5IGluIG1pbGxpc2Vjb25kcy5cbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIGFmdGVyIHRoZSBkZWxheS5cbiAqL1xuZnVuY3Rpb24gZGVsYXkobXM6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKTtcbiAgfSk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgcGxhdGZvcm0tc3BlY2lmaWMgY29tbWFuZCB0byBsYXVuY2ggT2JzaWRpYW4gd2l0aCByZW1vdGUgZGVidWdnaW5nIGVuYWJsZWQuXG4gKlxuICogQHBhcmFtIHBvcnQgLSBUaGUgQ0RQIHBvcnQgdG8gdXNlLlxuICogQHJldHVybnMgVGhlIHNoZWxsIGNvbW1hbmQgc3RyaW5nLlxuICovXG5mdW5jdGlvbiBnZXRPYnNpZGlhbkxhdW5jaENvbW1hbmQocG9ydDogbnVtYmVyKTogc3RyaW5nIHtcbiAgY29uc3QgZmxhZyA9IGAtLXJlbW90ZS1kZWJ1Z2dpbmctcG9ydD0ke1N0cmluZyhwb3J0KX1gO1xuXG4gIGlmIChwcm9jZXNzLnBsYXRmb3JtID09PSAnd2luMzInKSB7XG4gICAgcmV0dXJuIGBzdGFydCBcIlwiIFwiJUxPQ0FMQVBQREFUQSVcXFxcUHJvZ3JhbXNcXFxcT2JzaWRpYW5cXFxcT2JzaWRpYW4uZXhlXCIgJHtmbGFnfWA7XG4gIH1cblxuICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ2RhcndpbicpIHtcbiAgICByZXR1cm4gYC9BcHBsaWNhdGlvbnMvT2JzaWRpYW4uYXBwL0NvbnRlbnRzL01hY09TL09ic2lkaWFuICR7ZmxhZ30gJmA7XG4gIH1cblxuICByZXR1cm4gYG9ic2lkaWFuICR7ZmxhZ30gJmA7XG59XG5cbi8qIHY4IGlnbm9yZSBzdG9wICovXG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQXNCQSwwQkFBb0I7QUFPcEIsa0JBQXFCO0FBQ3JCLDZCQUFrQztBQUNsQyx5QkFBa0M7QUF1RGxDLE1BQU0sbUJBQW1CO0FBQ3pCLE1BQU0sa0NBQWtDO0FBQ3hDLE1BQU0sWUFBWTtBQUNsQixNQUFNLHNDQUFzQztBQUM1QyxNQUFNLHFDQUFxQztBQUMzQyxNQUFNLG9DQUFvQztBQUMxQyxNQUFNLDJDQUEyQztBQUNqRCxNQUFNLHFDQUFxQztBQVFwQyxNQUFNLG9CQUFpRDtBQUFBO0FBQUEsRUFFNUMsV0FBVztBQUFBLEVBQ25CLGtCQUFpQztBQUFBLEVBQ3hCO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxFQUNULFlBQVk7QUFBQSxFQUNaLEtBQXVCO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBT3hCLFlBQVksUUFBb0M7QUFDckQsVUFBTSxPQUFPLFFBQVEsV0FBVztBQUNoQyxTQUFLLFVBQVUsUUFBUSxXQUFXO0FBQ2xDLFNBQUssU0FB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
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file
|
|
3
|
+
*
|
|
4
|
+
* Desktop CDP transport — evaluates expressions via Chrome DevTools Protocol
|
|
5
|
+
* over WebSocket and manages vaults via Electron IPC.
|
|
6
|
+
*
|
|
7
|
+
* Obsidian exposes CDP on port 8315 by default. This transport connects to
|
|
8
|
+
* page targets, sends `Runtime.evaluate` commands, and routes to the correct
|
|
9
|
+
* vault target using `getBasePath()` probing.
|
|
10
|
+
*
|
|
11
|
+
* Advantages over CLI transport:
|
|
12
|
+
* - No CLI binary installation needed
|
|
13
|
+
* - No "CLI enabled" setting required in Obsidian
|
|
14
|
+
* - Lower overhead (WebSocket vs. process spawn per eval)
|
|
15
|
+
*
|
|
16
|
+
* Requirements:
|
|
17
|
+
* - Obsidian must be running with remote debugging enabled (port 8315)
|
|
18
|
+
* - Node.js 22+ (uses built-in `WebSocket` and `fetch` globals)
|
|
19
|
+
*/
|
|
20
|
+
import type { ObsidianTransport, TransportEvalOptions } from './transport.cjs';
|
|
21
|
+
/**
|
|
22
|
+
* Configuration for the CDP transport.
|
|
23
|
+
*/
|
|
24
|
+
export interface DesktopCdpTransportConfig {
|
|
25
|
+
/**
|
|
26
|
+
* CDP host. Defaults to `'localhost'`.
|
|
27
|
+
*/
|
|
28
|
+
cdpHost?: string;
|
|
29
|
+
/**
|
|
30
|
+
* CDP port. Defaults to `8315`.
|
|
31
|
+
*/
|
|
32
|
+
cdpPort?: number;
|
|
33
|
+
/**
|
|
34
|
+
* Timeout in milliseconds for individual CDP commands.
|
|
35
|
+
* Defaults to `30000`.
|
|
36
|
+
*/
|
|
37
|
+
commandTimeoutInMilliseconds?: number;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Transport that communicates with Desktop Obsidian via Chrome DevTools Protocol.
|
|
41
|
+
*
|
|
42
|
+
* Connects to Obsidian's CDP WebSocket endpoint, sends `Runtime.evaluate`
|
|
43
|
+
* commands, and routes expressions to the correct vault target.
|
|
44
|
+
*/
|
|
45
|
+
export declare class DesktopCdpTransport implements ObsidianTransport {
|
|
46
|
+
/** */
|
|
47
|
+
readonly isMobile = false;
|
|
48
|
+
private activeVaultPath;
|
|
49
|
+
private readonly cdpPort;
|
|
50
|
+
private readonly cdpUrl;
|
|
51
|
+
private readonly commandTimeoutInMilliseconds;
|
|
52
|
+
private messageId;
|
|
53
|
+
private ws;
|
|
54
|
+
/**
|
|
55
|
+
* Creates a new CDP transport.
|
|
56
|
+
*
|
|
57
|
+
* @param config - CDP connection configuration.
|
|
58
|
+
*/
|
|
59
|
+
constructor(config?: DesktopCdpTransportConfig);
|
|
60
|
+
/**
|
|
61
|
+
* Disposes of the active WebSocket connection.
|
|
62
|
+
*/
|
|
63
|
+
dispose(): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Evaluates a JavaScript expression inside Obsidian via CDP `Runtime.evaluate`.
|
|
66
|
+
*
|
|
67
|
+
* Routes to the correct vault target based on `options.cwd`.
|
|
68
|
+
*
|
|
69
|
+
* @param expression - The JavaScript expression to evaluate.
|
|
70
|
+
* @param options - Evaluation options.
|
|
71
|
+
* @returns The normalized result string.
|
|
72
|
+
*/
|
|
73
|
+
evaluate(expression: string, options: TransportEvalOptions): Promise<string>;
|
|
74
|
+
/**
|
|
75
|
+
* Verifies that the CDP endpoint is reachable and has Obsidian targets.
|
|
76
|
+
*
|
|
77
|
+
* If Obsidian is not running, attempts to auto-start it via URI protocol
|
|
78
|
+
* and polls until CDP becomes available.
|
|
79
|
+
*
|
|
80
|
+
* @param vaultPath - The vault path (used for vault registration check).
|
|
81
|
+
*/
|
|
82
|
+
preflightCheck(vaultPath: string): Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* Registers a vault via Electron IPC evaluated through CDP.
|
|
85
|
+
*
|
|
86
|
+
* Uses an existing Obsidian target to send the `vault-open` IPC command,
|
|
87
|
+
* then polls until the new vault's target appears.
|
|
88
|
+
*
|
|
89
|
+
* @param vaultPath - The absolute path to the vault folder.
|
|
90
|
+
*/
|
|
91
|
+
registerVault(vaultPath: string): Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* Unregisters a vault by destroying its window and removing it from the registry.
|
|
94
|
+
*
|
|
95
|
+
* @param vaultPath - The absolute path to the vault folder.
|
|
96
|
+
*/
|
|
97
|
+
unregisterVault(vaultPath: string): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* Connects to a CDP target's WebSocket endpoint.
|
|
100
|
+
*
|
|
101
|
+
* @param target - The CDP target to connect to.
|
|
102
|
+
* @returns The open WebSocket connection.
|
|
103
|
+
*/
|
|
104
|
+
private connectToTarget;
|
|
105
|
+
/**
|
|
106
|
+
* Disconnects the active WebSocket connection.
|
|
107
|
+
*/
|
|
108
|
+
private disconnect;
|
|
109
|
+
/**
|
|
110
|
+
* Ensures there is an active WebSocket connection to the correct vault target.
|
|
111
|
+
*
|
|
112
|
+
* Reuses the existing connection if it targets the requested vault.
|
|
113
|
+
* Otherwise, finds the correct target and reconnects.
|
|
114
|
+
*
|
|
115
|
+
* @param vaultPath - The vault path to target.
|
|
116
|
+
* @returns The active WebSocket connection.
|
|
117
|
+
*/
|
|
118
|
+
private ensureConnection;
|
|
119
|
+
/**
|
|
120
|
+
* Launches Obsidian with `--remote-debugging-port` and polls until CDP becomes available.
|
|
121
|
+
*/
|
|
122
|
+
private ensureObsidianRunning;
|
|
123
|
+
/**
|
|
124
|
+
* Finds the CDP target that has the given vault open.
|
|
125
|
+
*
|
|
126
|
+
* For a single target, returns it directly. For multiple targets,
|
|
127
|
+
* probes each by evaluating `getBasePath()` to find the match.
|
|
128
|
+
*
|
|
129
|
+
* @param vaultPath - The vault path to match.
|
|
130
|
+
* @returns The matching CDP target.
|
|
131
|
+
*/
|
|
132
|
+
private findTargetForVault;
|
|
133
|
+
/**
|
|
134
|
+
* Fetches the list of page-type targets from the CDP `/json` endpoint.
|
|
135
|
+
*
|
|
136
|
+
* @returns The list of page targets.
|
|
137
|
+
*/
|
|
138
|
+
private getPageTargets;
|
|
139
|
+
/**
|
|
140
|
+
* Probes a target to discover which vault path it has open.
|
|
141
|
+
*
|
|
142
|
+
* Creates a temporary WebSocket connection, evaluates `getBasePath()`,
|
|
143
|
+
* and returns the result.
|
|
144
|
+
*
|
|
145
|
+
* @param target - The CDP target to probe.
|
|
146
|
+
* @returns The vault's base path.
|
|
147
|
+
*/
|
|
148
|
+
private probeVaultPath;
|
|
149
|
+
/**
|
|
150
|
+
* Sends a CDP command over WebSocket and waits for the response.
|
|
151
|
+
*
|
|
152
|
+
* @param ws - The WebSocket connection.
|
|
153
|
+
* @param method - The CDP method name.
|
|
154
|
+
* @param params - The CDP method parameters.
|
|
155
|
+
* @returns The CDP response.
|
|
156
|
+
*/
|
|
157
|
+
private sendCommand;
|
|
158
|
+
}
|