obsidian-integration-testing 1.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.
- package/LICENSE +21 -0
- package/README.md +298 -0
- package/dist/lib/cjs/context-id.cjs +83 -0
- package/dist/lib/cjs/context-id.d.cts +57 -0
- package/dist/lib/cjs/exec.cjs +267 -0
- package/dist/lib/cjs/exec.d.cts +108 -0
- package/dist/lib/cjs/function-expression.cjs +41 -0
- package/dist/lib/cjs/function-expression.d.cts +16 -0
- package/dist/lib/cjs/index.cjs +40 -0
- package/dist/lib/cjs/index.d.cts +11 -0
- package/dist/lib/cjs/integration-global-setup.cjs +106 -0
- package/dist/lib/cjs/integration-global-setup.d.cts +32 -0
- package/dist/lib/cjs/json-with-functions.cjs +46 -0
- package/dist/lib/cjs/json-with-functions.d.cts +16 -0
- package/dist/lib/cjs/obsidian-cli.cjs +191 -0
- package/dist/lib/cjs/obsidian-cli.d.cts +75 -0
- package/dist/lib/cjs/obsidian-config.cjs +91 -0
- package/dist/lib/cjs/obsidian-config.d.cts +25 -0
- package/dist/lib/cjs/temp-vault.cjs +96 -0
- package/dist/lib/cjs/temp-vault.d.cts +47 -0
- package/dist/lib/cjs/type-guards.cjs +42 -0
- package/dist/lib/cjs/type-guards.d.cts +30 -0
- package/dist/lib/cjs/vault-registry.cjs +89 -0
- package/dist/lib/cjs/vault-registry.d.cts +18 -0
- package/dist/lib/esm/context-id.d.mts +57 -0
- package/dist/lib/esm/context-id.mjs +59 -0
- package/dist/lib/esm/exec.d.mts +108 -0
- package/dist/lib/esm/exec.mjs +232 -0
- package/dist/lib/esm/function-expression.d.mts +16 -0
- package/dist/lib/esm/function-expression.mjs +17 -0
- package/dist/lib/esm/index.d.mts +11 -0
- package/dist/lib/esm/index.mjs +15 -0
- package/dist/lib/esm/integration-global-setup.d.mts +32 -0
- package/dist/lib/esm/integration-global-setup.mjs +88 -0
- package/dist/lib/esm/json-with-functions.d.mts +16 -0
- package/dist/lib/esm/json-with-functions.mjs +22 -0
- package/dist/lib/esm/obsidian-cli.d.mts +75 -0
- package/dist/lib/esm/obsidian-cli.mjs +161 -0
- package/dist/lib/esm/obsidian-config.d.mts +25 -0
- package/dist/lib/esm/obsidian-config.mjs +58 -0
- package/dist/lib/esm/temp-vault.d.mts +47 -0
- package/dist/lib/esm/temp-vault.mjs +82 -0
- package/dist/lib/esm/type-guards.d.mts +30 -0
- package/dist/lib/esm/type-guards.mjs +17 -0
- package/dist/lib/esm/vault-registry.d.mts +18 -0
- package/dist/lib/esm/vault-registry.mjs +64 -0
- package/dist/obsidian-integration-testing-1.0.0.tgz +0 -0
- package/package.json +131 -0
- package/patches/@vitest+runner+4.1.0.patch +22 -0
- package/scripts/postinstall.mjs +29 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import process from "node:process";
|
|
3
|
+
import { exec } from "./exec.mjs";
|
|
4
|
+
import { getFunctionExpressionString } from "./function-expression.mjs";
|
|
5
|
+
import { jsonWithFunctions } from "./json-with-functions.mjs";
|
|
6
|
+
import {
|
|
7
|
+
getVaultId,
|
|
8
|
+
isCliEnabled,
|
|
9
|
+
isVaultRegistered
|
|
10
|
+
} from "./obsidian-config.mjs";
|
|
11
|
+
const NO_OUTPUT = "(no output)";
|
|
12
|
+
const UNABLE_TO_FIND_OBSIDIAN = "unable to find Obsidian";
|
|
13
|
+
const AUTO_START_POLL_INTERVAL_MS = 2e3;
|
|
14
|
+
const AUTO_START_TIMEOUT_MS = 3e4;
|
|
15
|
+
async function evalInObsidian(params) {
|
|
16
|
+
const { args = {}, contextId, fn, shouldSkipPreflightChecks = false, vaultPath } = params;
|
|
17
|
+
const cwd = vaultPath ?? process.cwd();
|
|
18
|
+
if (vaultPath !== void 0 && !existsSync(vaultPath)) {
|
|
19
|
+
throw new Error(`Vault path does not exist: ${vaultPath}`);
|
|
20
|
+
}
|
|
21
|
+
if (!shouldSkipPreflightChecks) {
|
|
22
|
+
if (!isVaultRegistered(cwd)) {
|
|
23
|
+
throw new Error(
|
|
24
|
+
`Vault is not registered in Obsidian: ${cwd}. Register the vault first with registerVault() or TempVault.register().`
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
if (!isCliEnabled()) {
|
|
28
|
+
throw new Error("Obsidian CLI is disabled. Enable it in Obsidian Settings \u2192 General \u2192 CLI.");
|
|
29
|
+
}
|
|
30
|
+
await assertObsidianCliAvailable();
|
|
31
|
+
}
|
|
32
|
+
const SLICE_START = 2;
|
|
33
|
+
const randomSuffix = String(Math.random()).slice(SLICE_START);
|
|
34
|
+
const contextExpr = contextId ? `((window.__obsidianContexts__ ??= {})["${String(contextId)}"] ??= {})` : "{}";
|
|
35
|
+
const expression = `
|
|
36
|
+
(async () => {
|
|
37
|
+
const fn${randomSuffix} = ${getFunctionExpressionString(fn)};
|
|
38
|
+
const obsidianModule${randomSuffix} = await (async () => {
|
|
39
|
+
if (!app.workspace.app.workspace.layoutReady) {
|
|
40
|
+
await new Promise((resolve) => app.workspace.onLayoutReady(resolve));
|
|
41
|
+
}
|
|
42
|
+
if (!app.plugins.isEnabled()) {
|
|
43
|
+
await app.plugins.setEnable(true);
|
|
44
|
+
}
|
|
45
|
+
${getFunctionExpressionString(getObsidianModulePluginFn)}
|
|
46
|
+
${getFunctionExpressionString(getObsidianModule)}
|
|
47
|
+
return await getObsidianModule();
|
|
48
|
+
})();
|
|
49
|
+
const args${randomSuffix} = ${jsonWithFunctions(args)};
|
|
50
|
+
const context${randomSuffix} = ${contextExpr};
|
|
51
|
+
const fullArgs${randomSuffix} = Object.assign(args${randomSuffix}, { app, obsidianModule: obsidianModule${randomSuffix}, context: context${randomSuffix} });
|
|
52
|
+
return JSON.stringify(await fn${randomSuffix}(fullArgs${randomSuffix}));
|
|
53
|
+
})()`;
|
|
54
|
+
const command = ["obsidian", "eval", `code=${expression}`];
|
|
55
|
+
let resultStr;
|
|
56
|
+
try {
|
|
57
|
+
resultStr = await exec(command, { cwd, isQuiet: true });
|
|
58
|
+
} catch (error) {
|
|
59
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
60
|
+
if (message.includes(UNABLE_TO_FIND_OBSIDIAN)) {
|
|
61
|
+
resultStr = await ensureObsidianRunning({ command, cwd });
|
|
62
|
+
} else {
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (resultStr === "" || resultStr === "Vault not found.") {
|
|
67
|
+
throw new Error(`Unexpected empty response from Obsidian CLI for path: ${cwd}`);
|
|
68
|
+
}
|
|
69
|
+
const resultJson = resultStr.startsWith("=> ") ? resultStr.slice("=> ".length) : resultStr;
|
|
70
|
+
if (resultJson === NO_OUTPUT) {
|
|
71
|
+
return void 0;
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
return JSON.parse(resultJson);
|
|
75
|
+
} catch {
|
|
76
|
+
throw new Error(`evalInObsidian: Obsidian returned non-JSON output: ${resultStr}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
async function assertObsidianCliAvailable() {
|
|
80
|
+
const command = process.platform === "win32" ? "where.exe obsidian.com" : "which obsidian";
|
|
81
|
+
try {
|
|
82
|
+
await exec(command, { isQuiet: true });
|
|
83
|
+
} catch {
|
|
84
|
+
throw new Error("Obsidian CLI is not available. Ensure Obsidian is installed and its CLI is in your PATH.");
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async function ensureObsidianRunning(params) {
|
|
88
|
+
console.warn("Obsidian is not running. Starting Obsidian...");
|
|
89
|
+
const vaultId = getVaultId(params.cwd);
|
|
90
|
+
const uri = vaultId ? `obsidian://open?vault=${vaultId}` : "obsidian://open";
|
|
91
|
+
try {
|
|
92
|
+
await exec(getOpenUriCommand(uri), { isQuiet: true });
|
|
93
|
+
} catch {
|
|
94
|
+
}
|
|
95
|
+
const deadline = Date.now() + AUTO_START_TIMEOUT_MS;
|
|
96
|
+
while (Date.now() < deadline) {
|
|
97
|
+
await new Promise((r) => {
|
|
98
|
+
setTimeout(r, AUTO_START_POLL_INTERVAL_MS);
|
|
99
|
+
});
|
|
100
|
+
try {
|
|
101
|
+
return await exec(params.command, { cwd: params.cwd, isQuiet: true });
|
|
102
|
+
} catch (error) {
|
|
103
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
104
|
+
if (!message.includes(UNABLE_TO_FIND_OBSIDIAN)) {
|
|
105
|
+
throw error;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
throw new Error(`Obsidian did not start within ${String(AUTO_START_TIMEOUT_MS)}ms.`);
|
|
110
|
+
}
|
|
111
|
+
async function getObsidianModule() {
|
|
112
|
+
const app = window.app;
|
|
113
|
+
const obsidianModuleHolder = app;
|
|
114
|
+
if (obsidianModuleHolder.obsidianModule) {
|
|
115
|
+
return obsidianModuleHolder.obsidianModule;
|
|
116
|
+
}
|
|
117
|
+
const SLICE_START = 2;
|
|
118
|
+
const randomSuffix = String(Math.random()).slice(SLICE_START);
|
|
119
|
+
const tempModuleName = `get-obsidian-module-${randomSuffix}`;
|
|
120
|
+
const dir = `${app.vault.configDir}/plugins/${tempModuleName}`;
|
|
121
|
+
app.plugins.manifests[tempModuleName] = {
|
|
122
|
+
author: "",
|
|
123
|
+
description: "",
|
|
124
|
+
dir,
|
|
125
|
+
id: tempModuleName,
|
|
126
|
+
isDesktopOnly: true,
|
|
127
|
+
minAppVersion: "",
|
|
128
|
+
name: tempModuleName,
|
|
129
|
+
version: ""
|
|
130
|
+
};
|
|
131
|
+
await app.vault.adapter.mkdir(dir);
|
|
132
|
+
await app.vault.adapter.write(`${dir}/main.js`, `(${String(getObsidianModulePluginFn)})();`);
|
|
133
|
+
await app.plugins.loadPlugin(tempModuleName);
|
|
134
|
+
await app.plugins.uninstallPlugin(tempModuleName);
|
|
135
|
+
if (obsidianModuleHolder.obsidianModule) {
|
|
136
|
+
return obsidianModuleHolder.obsidianModule;
|
|
137
|
+
}
|
|
138
|
+
throw new Error("Failed to load obsidian module");
|
|
139
|
+
}
|
|
140
|
+
function getObsidianModulePluginFn() {
|
|
141
|
+
const app = window.app;
|
|
142
|
+
const obsidianModuleHolder = app;
|
|
143
|
+
const pluginRequire = require;
|
|
144
|
+
const pluginExports = exports;
|
|
145
|
+
const obsidianModule = pluginRequire("obsidian");
|
|
146
|
+
obsidianModuleHolder.obsidianModule = obsidianModule;
|
|
147
|
+
pluginExports.default = obsidianModule.Plugin;
|
|
148
|
+
}
|
|
149
|
+
function getOpenUriCommand(uri) {
|
|
150
|
+
if (process.platform === "win32") {
|
|
151
|
+
return `start "" "${uri}"`;
|
|
152
|
+
}
|
|
153
|
+
if (process.platform === "darwin") {
|
|
154
|
+
return `open "${uri}"`;
|
|
155
|
+
}
|
|
156
|
+
return `xdg-open "${uri}"`;
|
|
157
|
+
}
|
|
158
|
+
export {
|
|
159
|
+
evalInObsidian
|
|
160
|
+
};
|
|
161
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL29ic2lkaWFuLWNsaS50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAcGFja2FnZURvY3VtZW50YXRpb25cbiAqXG4gKiBFdmFsdWF0ZXMgYSBmdW5jdGlvbiBpbnNpZGUgYSBydW5uaW5nIE9ic2lkaWFuIGluc3RhbmNlIHZpYSB0aGUgT2JzaWRpYW4gQ0xJLlxuICovXG5cbmltcG9ydCB0eXBlIHsgQXBwIH0gZnJvbSAnb2JzaWRpYW4nO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC14L25vLW5hbWVzcGFjZSAtLSBXZSBuZWVkIHRvIHJlZmVyZW5jZSBgb2JzaWRpYW5gIG1vZHVsZS5cbmltcG9ydCB0eXBlICogYXMgb2JzaWRpYW4gZnJvbSAnb2JzaWRpYW4nO1xuaW1wb3J0IHR5cGUgeyBQcm9taXNhYmxlIH0gZnJvbSAndHlwZS1mZXN0JztcblxuaW1wb3J0IHsgZXhpc3RzU3luYyB9IGZyb20gJ25vZGU6ZnMnO1xuaW1wb3J0IHByb2Nlc3MgZnJvbSAnbm9kZTpwcm9jZXNzJztcblxuaW1wb3J0IHR5cGUge1xuICBDb250ZXh0QXJncyxcbiAgQ29udGV4dElkXG59IGZyb20gJy4vY29udGV4dC1pZC5tanMnO1xuXG5pbXBvcnQgeyBleGVjIH0gZnJvbSAnLi9leGVjLm1qcyc7XG5pbXBvcnQgeyBnZXRGdW5jdGlvbkV4cHJlc3Npb25TdHJpbmcgfSBmcm9tICcuL2Z1bmN0aW9uLWV4cHJlc3Npb24ubWpzJztcbmltcG9ydCB7IGpzb25XaXRoRnVuY3Rpb25zIH0gZnJvbSAnLi9qc29uLXdpdGgtZnVuY3Rpb25zLm1qcyc7XG5pbXBvcnQge1xuICBnZXRWYXVsdElkLFxuICBpc0NsaUVuYWJsZWQsXG4gIGlzVmF1bHRSZWdpc3RlcmVkXG59IGZyb20gJy4vb2JzaWRpYW4tY29uZmlnLm1qcyc7XG5cbmNvbnN0IE5PX09VVFBVVCA9ICcobm8gb3V0cHV0KSc7XG5jb25zdCBVTkFCTEVfVE9fRklORF9PQlNJRElBTiA9ICd1bmFibGUgdG8gZmluZCBPYnNpZGlhbic7XG5jb25zdCBBVVRPX1NUQVJUX1BPTExfSU5URVJWQUxfTVMgPSAyMDAwO1xuY29uc3QgQVVUT19TVEFSVF9USU1FT1VUX01TID0gMzAwMDA7XG5cbi8qKlxuICogQ29tbW9uIGFyZ3VtZW50cyBhdXRvbWF0aWNhbGx5IHByb3ZpZGVkIHRvIGV2ZXJ5IHtAbGluayBldmFsSW5PYnNpZGlhbn0gY2FsbGJhY2suXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ29tbW9uQXJncyB7XG4gIC8qKlxuICAgKiBUaGUgT2JzaWRpYW4ge0BsaW5rIEFwcH0gaW5zdGFuY2UuXG4gICAqL1xuICBhcHA6IEFwcDtcblxuICAvKipcbiAgICogVGhlIGBvYnNpZGlhbmAgbW9kdWxlLCByZXNvbHZlZCBhdCBydW50aW1lIGluc2lkZSB0aGUgT2JzaWRpYW4gcHJvY2Vzcy5cbiAgICovXG4gIG9ic2lkaWFuTW9kdWxlOiB0eXBlb2Ygb2JzaWRpYW47XG59XG5cbi8qKlxuICogUGFyYW1ldGVycyBmb3Ige0BsaW5rIGV2YWxJbk9ic2lkaWFufS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFdmFsSW5PYnNpZGlhblBhcmFtczxBcmdzIGV4dGVuZHMgR2VuZXJpY09iamVjdCwgUmVzdWx0LCBUQ29udGV4dElkIGV4dGVuZHMgQ29udGV4dElkPHVua25vd24+IHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkPiB7XG4gIC8qKlxuICAgKiBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBmdW5jdGlvbi4gVmFsdWVzIG1heSBpbmNsdWRlIGZ1bmN0aW9ucyBcdTIwMTRcbiAgICogdGhleSBhcmUgc2VyaWFsaXplZCB2aWEgYHRvU3RyaW5nKClgLlxuICAgKi9cbiAgYXJncz86IEFyZ3M7XG5cbiAgLyoqXG4gICAqIEEge0BsaW5rIENvbnRleHRJZH0gbGlua2luZyB0aGlzIGNhbGwgdG8gYSBwZXJzaXN0ZW50IHN0b3JlIG9uIGB3aW5kb3dgXG4gICAqIGluIHRoZSBPYnNpZGlhbiBwcm9jZXNzLiBUaGUgY2FsbGJhY2sgcmVjZWl2ZXMgYSB0eXBlZCBgY29udGV4dGAgb2JqZWN0XG4gICAqIHRoYXQgc3Vydml2ZXMgYWNyb3NzIGNhbGxzIHNoYXJpbmcgdGhlIHNhbWUgSUQuXG4gICAqXG4gICAqIFdoZW4gb21pdHRlZCwgYGNvbnRleHRgIGlzIGEgZnJlc2ggZW1wdHkgb2JqZWN0IGVhY2ggY2FsbC5cbiAgICovXG4gIGNvbnRleHRJZD86IFRDb250ZXh0SWQ7XG5cbiAgLyoqXG4gICAqIFRoZSBmdW5jdGlvbiB0byBldmFsdWF0ZSBpbiB0aGUgT2JzaWRpYW4gY29udGV4dC5cbiAgICovXG4gIGZuKGFyZ3M6IEFyZ3MgJiBDb21tb25BcmdzICYgQ29udGV4dEFyZ3M8VENvbnRleHRJZD4pOiBQcm9taXNhYmxlPFJlc3VsdD47XG5cbiAgLyoqXG4gICAqIFNraXBzIHByZS1mbGlnaHQgY2hlY2tzICh2YXVsdCByZWdpc3RyYXRpb24sIENMSSBhdmFpbGFiaWxpdHkpLlxuICAgKiBVc2VkIGludGVybmFsbHkgYnkgdmF1bHQgcmVnaXN0cmF0aW9uIGZ1bmN0aW9ucy5cbiAgICpcbiAgICogQGludGVybmFsXG4gICAqL1xuICBzaG91bGRTa2lwUHJlZmxpZ2h0Q2hlY2tzPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogVGhlIHBhdGggdG8gdGhlIE9ic2lkaWFuIHZhdWx0LiBEZWZhdWx0cyB0byBgcHJvY2Vzcy5jd2QoKWAuXG4gICAqL1xuICB2YXVsdFBhdGg/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogQSBwbGFpbiBvYmplY3Qgd2l0aCBzdHJpbmcga2V5cy5cbiAqL1xuZXhwb3J0IHR5cGUgR2VuZXJpY09iamVjdCA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuXG4vKipcbiAqIEV2YWx1YXRlcyBhIGZ1bmN0aW9uIGluc2lkZSB0aGUgcnVubmluZyBPYnNpZGlhbiBpbnN0YW5jZVxuICogdmlhIHRoZSBPYnNpZGlhbiBDTEkgYW5kIHJldHVybnMgdGhlIHBhcnNlZCByZXN1bHQuXG4gKlxuICogVGhlIGZ1bmN0aW9uIHJlY2VpdmVzIGFuIGFyZ3Mgb2JqZWN0IHRoYXQgaW5jbHVkZXMgYGFwcGAsIGBvYnNpZGlhbk1vZHVsZWAsXG4gKiBgY29udGV4dGAsIGFuZCBhbnkgYWRkaXRpb25hbCBgYXJnc2AgcGFzc2VkIGJ5IHRoZSBjYWxsZXIuXG4gKiBJdCBpcyBzZXJpYWxpemVkIHZpYSBgdG9TdHJpbmcoKWAgYW5kIGludm9rZWQgYXMgYW4gSUlGRS5cbiAqIFRoZSBmdW5jdGlvbiBtdXN0IGJlIHNlbGYtY29udGFpbmVkIFx1MjAxNCBjbG9zdXJlcyBvdmVyIGxvY2FsIHZhcmlhYmxlcyB3aWxsIG5vdCB3b3JrLlxuICogUGFzcyBhbnkgbmVlZGVkIHZhbHVlcyBhcyBgYXJnc2AgXHUyMDE0IHRoZXkgYXJlIEpTT04tc2VyaWFsaXplZCBhbmQgZGVzZXJpYWxpemVkIG9uIHRoZSBPYnNpZGlhbiBzaWRlLlxuICpcbiAqIFRoZSByZXN1bHQgaXMgYEpTT04uc3RyaW5naWZ5YCdkIG9uIHRoZSBPYnNpZGlhbiBzaWRlIGFuZCBwYXJzZWQgYmFjay5cbiAqXG4gKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBmdW5jdGlvbiB0byBldmFsdWF0ZS5cbiAqIEByZXR1cm5zIEEge0BsaW5rIFByb21pc2V9IHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHJldHVybiB2YWx1ZSBvZiBgZm5gLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZXZhbEluT2JzaWRpYW48QXJncyBleHRlbmRzIEdlbmVyaWNPYmplY3QsIFJlc3VsdCwgVENvbnRleHRJZCBleHRlbmRzIENvbnRleHRJZDx1bmtub3duPiB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZD4oXG4gIHBhcmFtczogRXZhbEluT2JzaWRpYW5QYXJhbXM8QXJncywgUmVzdWx0LCBUQ29udGV4dElkPlxuKTogUHJvbWlzZTxSZXN1bHQ+IHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC91bmJvdW5kLW1ldGhvZCAtLSBgZm5gIGNhbiBiZSB1bmJvdW5kLlxuICBjb25zdCB7IGFyZ3MgPSB7fSwgY29udGV4dElkLCBmbiwgc2hvdWxkU2tpcFByZWZsaWdodENoZWNrcyA9IGZhbHNlLCB2YXVsdFBhdGggfSA9IHBhcmFtcztcbiAgY29uc3QgY3dkID0gdmF1bHRQYXRoID8/IHByb2Nlc3MuY3dkKCk7XG5cbiAgLy8gQ2hlY2sgMTogVmF1bHQgcGF0aCBleGlzdHMgb24gZGlzay5cbiAgaWYgKHZhdWx0UGF0aCAhPT0gdW5kZWZpbmVkICYmICFleGlzdHNTeW5jKHZhdWx0UGF0aCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFZhdWx0IHBhdGggZG9lcyBub3QgZXhpc3Q6ICR7dmF1bHRQYXRofWApO1xuICB9XG5cbiAgaWYgKCFzaG91bGRTa2lwUHJlZmxpZ2h0Q2hlY2tzKSB7XG4gICAgLy8gQ2hlY2sgMjogVmF1bHQgaXMgcmVnaXN0ZXJlZCBpbiBPYnNpZGlhbi5cbiAgICBpZiAoIWlzVmF1bHRSZWdpc3RlcmVkKGN3ZCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFZhdWx0IGlzIG5vdCByZWdpc3RlcmVkIGluIE9ic2lkaWFuOiAke2N3ZH0uIFJlZ2lzdGVyIHRoZSB2YXVsdCBmaXJzdCB3aXRoIHJlZ2lzdGVyVmF1bHQoKSBvciBUZW1wVmF1bHQucmVnaXN0ZXIoKS5gXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIENoZWNrIDM6IENMSSBpcyBlbmFibGVkIGluIE9ic2lkaWFuIHNldHRpbmdzLlxuICAgIGlmICghaXNDbGlFbmFibGVkKCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignT2JzaWRpYW4gQ0xJIGlzIGRpc2FibGVkLiBFbmFibGUgaXQgaW4gT2JzaWRpYW4gU2V0dGluZ3MgXFx1MjE5MiBHZW5lcmFsIFxcdTIxOTIgQ0xJLicpO1xuICAgIH1cblxuICAgIC8vIENoZWNrIDQ6IE9ic2lkaWFuIENMSSBiaW5hcnkgaXMgaW4gUEFUSC5cbiAgICBhd2FpdCBhc3NlcnRPYnNpZGlhbkNsaUF2YWlsYWJsZSgpO1xuICB9XG5cbiAgY29uc3QgU0xJQ0VfU1RBUlQgPSAyO1xuICBjb25zdCByYW5kb21TdWZmaXggPSBTdHJpbmcoTWF0aC5yYW5kb20oKSkuc2xpY2UoU0xJQ0VfU1RBUlQpO1xuICBjb25zdCBjb250ZXh0RXhwciA9IGNvbnRleHRJZFxuICAgID8gYCgod2luZG93Ll9fb2JzaWRpYW5Db250ZXh0c19fID8/PSB7fSlbXCIke1N0cmluZyhjb250ZXh0SWQpfVwiXSA/Pz0ge30pYFxuICAgIDogJ3t9JztcbiAgY29uc3QgZXhwcmVzc2lvbiA9IGBcbihhc3luYyAoKSA9PiB7XG4gIGNvbnN0IGZuJHtyYW5kb21TdWZmaXh9ID0gJHtnZXRGdW5jdGlvbkV4cHJlc3Npb25TdHJpbmcoZm4pfTtcbiAgY29uc3Qgb2JzaWRpYW5Nb2R1bGUke3JhbmRvbVN1ZmZpeH0gPSBhd2FpdCAoYXN5bmMgKCkgPT4ge1xuICAgIGlmICghYXBwLndvcmtzcGFjZS5hcHAud29ya3NwYWNlLmxheW91dFJlYWR5KSB7XG4gICAgICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gYXBwLndvcmtzcGFjZS5vbkxheW91dFJlYWR5KHJlc29sdmUpKTtcbiAgICB9XG4gICAgaWYgKCFhcHAucGx1Z2lucy5pc0VuYWJsZWQoKSkge1xuICAgICAgYXdhaXQgYXBwLnBsdWdpbnMuc2V0RW5hYmxlKHRydWUpO1xuICAgIH1cbiAgICAke2dldEZ1bmN0aW9uRXhwcmVzc2lvblN0cmluZyhnZXRPYnNpZGlhbk1vZHVsZVBsdWdpbkZuKX1cbiAgICAke2dldEZ1bmN0aW9uRXhwcmVzc2lvblN0cmluZyhnZXRPYnNpZGlhbk1vZHVsZSl9XG4gICAgcmV0dXJuIGF3YWl0IGdldE9ic2lkaWFuTW9kdWxlKCk7XG4gIH0pKCk7XG4gIGNvbnN0IGFyZ3Mke3JhbmRvbVN1ZmZpeH0gPSAke2pzb25XaXRoRnVuY3Rpb25zKGFyZ3MpfTtcbiAgY29uc3QgY29udGV4dCR7cmFuZG9tU3VmZml4fSA9ICR7Y29udGV4dEV4cHJ9O1xuICBjb25zdCBmdWxsQXJncyR7cmFuZG9tU3VmZml4fSA9IE9iamVjdC5hc3NpZ24oYXJncyR7cmFuZG9tU3VmZml4fSwgeyBhcHAsIG9ic2lkaWFuTW9kdWxlOiBvYnNpZGlhbk1vZHVsZSR7cmFuZG9tU3VmZml4fSwgY29udGV4dDogY29udGV4dCR7cmFuZG9tU3VmZml4fSB9KTtcbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGF3YWl0IGZuJHtyYW5kb21TdWZmaXh9KGZ1bGxBcmdzJHtyYW5kb21TdWZmaXh9KSk7XG59KSgpYDtcblxuICBjb25zdCBjb21tYW5kID0gWydvYnNpZGlhbicsICdldmFsJywgYGNvZGU9JHtleHByZXNzaW9ufWBdO1xuXG4gIGxldCByZXN1bHRTdHI6IHN0cmluZztcbiAgdHJ5IHtcbiAgICByZXN1bHRTdHIgPSBhd2FpdCBleGVjKGNvbW1hbmQsIHsgY3dkLCBpc1F1aWV0OiB0cnVlIH0pO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGNvbnN0IG1lc3NhZ2UgPSBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcik7XG4gICAgaWYgKG1lc3NhZ2UuaW5jbHVkZXMoVU5BQkxFX1RPX0ZJTkRfT0JTSURJQU4pKSB7XG4gICAgICAvLyBDaGVjayA1OiBPYnNpZGlhbiBpcyBub3QgcnVubmluZyBcdTIwMTQgYXV0by1zdGFydCBpdC5cbiAgICAgIHJlc3VsdFN0ciA9IGF3YWl0IGVuc3VyZU9ic2lkaWFuUnVubmluZyh7IGNvbW1hbmQsIGN3ZCB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG5cbiAgaWYgKHJlc3VsdFN0ciA9PT0gJycgfHwgcmVzdWx0U3RyID09PSAnVmF1bHQgbm90IGZvdW5kLicpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFVuZXhwZWN0ZWQgZW1wdHkgcmVzcG9uc2UgZnJvbSBPYnNpZGlhbiBDTEkgZm9yIHBhdGg6ICR7Y3dkfWApO1xuICB9XG5cbiAgY29uc3QgcmVzdWx0SnNvbiA9IHJlc3VsdFN0ci5zdGFydHNXaXRoKCc9PiAnKSA/IHJlc3VsdFN0ci5zbGljZSgnPT4gJy5sZW5ndGgpIDogcmVzdWx0U3RyO1xuICBpZiAocmVzdWx0SnNvbiA9PT0gTk9fT1VUUFVUKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZCBhcyBSZXN1bHQ7XG4gIH1cblxuICB0cnkge1xuICAgIHJldHVybiBKU09OLnBhcnNlKHJlc3VsdEpzb24pIGFzIFJlc3VsdDtcbiAgfSBjYXRjaCB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBldmFsSW5PYnNpZGlhbjogT2JzaWRpYW4gcmV0dXJuZWQgbm9uLUpTT04gb3V0cHV0OiAke3Jlc3VsdFN0cn1gKTtcbiAgfVxufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIHRoZSBPYnNpZGlhbiBDTEkgYmluYXJ5IGlzIGF2YWlsYWJsZSBpbiB0aGUgc3lzdGVtIFBBVEguXG4gKlxuICogQHRocm93cyBJZiB0aGUgQ0xJIGJpbmFyeSBpcyBub3QgZm91bmQuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGFzc2VydE9ic2lkaWFuQ2xpQXZhaWxhYmxlKCk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBjb21tYW5kID0gcHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ3dpbjMyJyA/ICd3aGVyZS5leGUgb2JzaWRpYW4uY29tJyA6ICd3aGljaCBvYnNpZGlhbic7XG4gIHRyeSB7XG4gICAgYXdhaXQgZXhlYyhjb21tYW5kLCB7IGlzUXVpZXQ6IHRydWUgfSk7XG4gIH0gY2F0Y2gge1xuICAgIHRocm93IG5ldyBFcnJvcignT2JzaWRpYW4gQ0xJIGlzIG5vdCBhdmFpbGFibGUuIEVuc3VyZSBPYnNpZGlhbiBpcyBpbnN0YWxsZWQgYW5kIGl0cyBDTEkgaXMgaW4geW91ciBQQVRILicpO1xuICB9XG59XG5cbi8qKlxuICogTGF1bmNoZXMgT2JzaWRpYW4gdmlhIHRoZSBgb2JzaWRpYW46Ly9gIFVSSSBwcm90b2NvbCBhbmQgcmV0cmllcyB0aGUgZXZhbFxuICogdW50aWwgT2JzaWRpYW4gYmVjb21lcyBhdmFpbGFibGUuXG4gKlxuICogQHBhcmFtIHBhcmFtcyAtIFRoZSBleGVjIHBhcmFtZXRlcnMgZm9yIHRoZSBldmFsIGNvbW1hbmQuXG4gKiBAcGFyYW0gcGFyYW1zLmNvbW1hbmQgLSBUaGUgQ0xJIGNvbW1hbmQgYXJyYXkgdG8gcmV0cnkuXG4gKiBAcGFyYW0gcGFyYW1zLmN3ZCAtIFRoZSB3b3JraW5nIGRpcmVjdG9yeSBmb3IgdGhlIGV2YWwgY29tbWFuZC5cbiAqIEByZXR1cm5zIFRoZSByZXN1bHQgc3RyaW5nIGZyb20gdGhlIHN1Y2Nlc3NmdWwgZXZhbC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZW5zdXJlT2JzaWRpYW5SdW5uaW5nKHBhcmFtczogeyBjb21tYW5kOiBzdHJpbmdbXTsgY3dkOiBzdHJpbmcgfSk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnNvbGUud2FybignT2JzaWRpYW4gaXMgbm90IHJ1bm5pbmcuIFN0YXJ0aW5nIE9ic2lkaWFuLi4uJyk7XG5cbiAgY29uc3QgdmF1bHRJZCA9IGdldFZhdWx0SWQocGFyYW1zLmN3ZCk7XG4gIGNvbnN0IHVyaSA9IHZhdWx0SWQgPyBgb2JzaWRpYW46Ly9vcGVuP3ZhdWx0PSR7dmF1bHRJZH1gIDogJ29ic2lkaWFuOi8vb3Blbic7XG5cbiAgdHJ5IHtcbiAgICBhd2FpdCBleGVjKGdldE9wZW5VcmlDb21tYW5kKHVyaSksIHsgaXNRdWlldDogdHJ1ZSB9KTtcbiAgfSBjYXRjaCB7XG4gICAgLy8gVGhlIG9wZW4gY29tbWFuZCBtYXkgZmFpbCBvbiBzb21lIHN5c3RlbXMgXHUyMDE0IHdlJ2xsIHN0aWxsIHRyeSBwb2xsaW5nLlxuICB9XG5cbiAgY29uc3QgZGVhZGxpbmUgPSBEYXRlLm5vdygpICsgQVVUT19TVEFSVF9USU1FT1VUX01TO1xuICB3aGlsZSAoRGF0ZS5ub3coKSA8IGRlYWRsaW5lKSB7XG4gICAgYXdhaXQgbmV3IFByb21pc2UoKHIpID0+IHtcbiAgICAgIHNldFRpbWVvdXQociwgQVVUT19TVEFSVF9QT0xMX0lOVEVSVkFMX01TKTtcbiAgICB9KTtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IGV4ZWMocGFyYW1zLmNvbW1hbmQsIHsgY3dkOiBwYXJhbXMuY3dkLCBpc1F1aWV0OiB0cnVlIH0pO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zdCBtZXNzYWdlID0gZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpO1xuICAgICAgaWYgKCFtZXNzYWdlLmluY2x1ZGVzKFVOQUJMRV9UT19GSU5EX09CU0lESUFOKSkge1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYE9ic2lkaWFuIGRpZCBub3Qgc3RhcnQgd2l0aGluICR7U3RyaW5nKEFVVE9fU1RBUlRfVElNRU9VVF9NUyl9bXMuYCk7XG59XG5cbi8qIHY4IGlnbm9yZSBzdGFydCAtLSBTZXJpYWxpemVkIHZpYSB0b1N0cmluZygpIGFuZCBleGVjdXRlZCBpbnNpZGUgdGhlIE9ic2lkaWFuIHByb2Nlc3MsIG5vdCBpbiBOb2RlLiBDb3ZlcmVkIGJ5IGludGVncmF0aW9uIHRlc3RzLiAqL1xuXG4vKipcbiAqIEluamVjdGVkIGludG8gdGhlIE9ic2lkaWFuIHByb2Nlc3MgdG8gcmVzb2x2ZSB0aGUgYG9ic2lkaWFuYCBtb2R1bGUuXG4gKiBVc2VzIGEgY2FjaGVkIHZhbHVlIG9uIGBhcHBgIGlmIGF2YWlsYWJsZSwgb3RoZXJ3aXNlIGluc3RhbGxzIGEgdGVtcG9yYXJ5XG4gKiBwbHVnaW4gdGhhdCBjYWxscyBgcmVxdWlyZSgnb2JzaWRpYW4nKWAgYW5kIGNhY2hlcyB0aGUgcmVzdWx0LlxuICpcbiAqIE11c3QgTk9UIHJlZmVyZW5jZSBhbnkgb3V0ZXIgc2NvcGUgXHUyMDE0IGl0IGlzIHNlcmlhbGl6ZWQgdmlhIGB0b1N0cmluZygpYC5cbiAqIGBnZXRPYnNpZGlhbk1vZHVsZVBsdWdpbkZuYCBtdXN0IGJlIGRlZmluZWQgaW4gdGhlIHNhbWUgc2NvcGVcbiAqICh0aGUgZ2VuZXJhdGVkIElJRkUgaGFuZGxlcyB0aGlzKS5cbiAqXG4gKiBAcmV0dXJucyBUaGUgYG9ic2lkaWFuYCBtb2R1bGUuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGdldE9ic2lkaWFuTW9kdWxlKCk6IFByb21pc2U8dHlwZW9mIG9ic2lkaWFuPiB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZGVwcmVjYXRlZCAtLSBXZSBuZWVkIGdsb2JhbCBgYXBwYCB2YXJpYWJsZS5cbiAgY29uc3QgYXBwID0gd2luZG93LmFwcDtcbiAgaW50ZXJmYWNlIE9ic2lkaWFuTW9kdWxlSG9sZGVyIHtcbiAgICBvYnNpZGlhbk1vZHVsZTogdHlwZW9mIG9ic2lkaWFuO1xuICB9XG4gIGNvbnN0IG9ic2lkaWFuTW9kdWxlSG9sZGVyID0gYXBwIGFzIFBhcnRpYWw8T2JzaWRpYW5Nb2R1bGVIb2xkZXI+O1xuICBpZiAob2JzaWRpYW5Nb2R1bGVIb2xkZXIub2JzaWRpYW5Nb2R1bGUpIHtcbiAgICByZXR1cm4gb2JzaWRpYW5Nb2R1bGVIb2xkZXIub2JzaWRpYW5Nb2R1bGU7XG4gIH1cbiAgY29uc3QgU0xJQ0VfU1RBUlQgPSAyO1xuICBjb25zdCByYW5kb21TdWZmaXggPSBTdHJpbmcoTWF0aC5yYW5kb20oKSkuc2xpY2UoU0xJQ0VfU1RBUlQpO1xuICBjb25zdCB0ZW1wTW9kdWxlTmFtZSA9IGBnZXQtb2JzaWRpYW4tbW9kdWxlLSR7cmFuZG9tU3VmZml4fWA7XG4gIGNvbnN0IGRpciA9IGAke2FwcC52YXVsdC5jb25maWdEaXJ9L3BsdWdpbnMvJHt0ZW1wTW9kdWxlTmFtZX1gO1xuICBhcHAucGx1Z2lucy5tYW5pZmVzdHNbdGVtcE1vZHVsZU5hbWVdID0ge1xuICAgIGF1dGhvcjogJycsXG4gICAgZGVzY3JpcHRpb246ICcnLFxuICAgIGRpcixcbiAgICBpZDogdGVtcE1vZHVsZU5hbWUsXG4gICAgaXNEZXNrdG9wT25seTogdHJ1ZSxcbiAgICBtaW5BcHBWZXJzaW9uOiAnJyxcbiAgICBuYW1lOiB0ZW1wTW9kdWxlTmFtZSxcbiAgICB2ZXJzaW9uOiAnJ1xuICB9O1xuICBhd2FpdCBhcHAudmF1bHQuYWRhcHRlci5ta2RpcihkaXIpO1xuICBhd2FpdCBhcHAudmF1bHQuYWRhcHRlci53cml0ZShgJHtkaXJ9L21haW4uanNgLCBgKCR7U3RyaW5nKGdldE9ic2lkaWFuTW9kdWxlUGx1Z2luRm4pfSkoKTtgKTtcbiAgYXdhaXQgYXBwLnBsdWdpbnMubG9hZFBsdWdpbih0ZW1wTW9kdWxlTmFtZSk7XG4gIGF3YWl0IGFwcC5wbHVnaW5zLnVuaW5zdGFsbFBsdWdpbih0ZW1wTW9kdWxlTmFtZSk7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5uZWNlc3NhcnktY29uZGl0aW9uIC0tIEl0IHdpbGwgYmUgaW5pdGlhbGl6ZWQgd2l0aGluIGBsb2FkUGx1Z2luYC5cbiAgaWYgKG9ic2lkaWFuTW9kdWxlSG9sZGVyLm9ic2lkaWFuTW9kdWxlKSB7XG4gICAgcmV0dXJuIG9ic2lkaWFuTW9kdWxlSG9sZGVyLm9ic2lkaWFuTW9kdWxlO1xuICB9XG4gIHRocm93IG5ldyBFcnJvcignRmFpbGVkIHRvIGxvYWQgb2JzaWRpYW4gbW9kdWxlJyk7XG59XG5cbi8qKlxuICogVGhlIGJvZHkgb2YgdGhlIHRlbXBvcmFyeSBwbHVnaW4gdGhhdCBleHRyYWN0cyB0aGUgYG9ic2lkaWFuYCBtb2R1bGUuXG4gKiBTZXJpYWxpemVkIHZpYSBgdG9TdHJpbmcoKWAgYW5kIHdyaXR0ZW4gdG8gYG1haW4uanNgIGJ5IHtAbGluayBnZXRPYnNpZGlhbk1vZHVsZX0uXG4gKiBNdXN0IE5PVCByZWZlcmVuY2UgYW55IG91dGVyIHNjb3BlLlxuICovXG5mdW5jdGlvbiBnZXRPYnNpZGlhbk1vZHVsZVBsdWdpbkZuKCk6IHZvaWQge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWRlcHJlY2F0ZWQgLS0gV2UgbmVlZCBnbG9iYWwgYGFwcGAgdmFyaWFibGUuXG4gIGNvbnN0IGFwcCA9IHdpbmRvdy5hcHA7XG4gIGludGVyZmFjZSBPYnNpZGlhbk1vZHVsZUhvbGRlciB7XG4gICAgb2JzaWRpYW5Nb2R1bGU6IHR5cGVvZiBvYnNpZGlhbjtcbiAgfVxuICBjb25zdCBvYnNpZGlhbk1vZHVsZUhvbGRlciA9IGFwcCBhcyBQYXJ0aWFsPE9ic2lkaWFuTW9kdWxlSG9sZGVyPjtcblxuICBjb25zdCBwbHVnaW5SZXF1aXJlID0gcmVxdWlyZTtcbiAgY29uc3QgcGx1Z2luRXhwb3J0cyA9IGV4cG9ydHMgYXMge1xuICAgIGRlZmF1bHQ6IHVua25vd247XG4gIH07XG5cbiAgY29uc3Qgb2JzaWRpYW5Nb2R1bGUgPSBwbHVnaW5SZXF1aXJlKCdvYnNpZGlhbicpIGFzIHR5cGVvZiBvYnNpZGlhbjtcbiAgb2JzaWRpYW5Nb2R1bGVIb2xkZXIub2JzaWRpYW5Nb2R1bGUgPSBvYnNpZGlhbk1vZHVsZTtcbiAgcGx1Z2luRXhwb3J0cy5kZWZhdWx0ID0gb2JzaWRpYW5Nb2R1bGUuUGx1Z2luO1xufVxuXG4vKiB2OCBpZ25vcmUgc3RvcCAqL1xuXG4vKipcbiAqIFJldHVybnMgdGhlIHBsYXRmb3JtLXNwZWNpZmljIGNvbW1hbmQgdG8gb3BlbiBhIFVSSS5cbiAqXG4gKiBAcGFyYW0gdXJpIC0gVGhlIFVSSSB0byBvcGVuLlxuICogQHJldHVybnMgVGhlIHNoZWxsIGNvbW1hbmQgc3RyaW5nLlxuICovXG5mdW5jdGlvbiBnZXRPcGVuVXJpQ29tbWFuZCh1cmk6IHN0cmluZyk6IHN0cmluZyB7XG4gIGlmIChwcm9jZXNzLnBsYXRmb3JtID09PSAnd2luMzInKSB7XG4gICAgcmV0dXJuIGBzdGFydCBcIlwiIFwiJHt1cml9XCJgO1xuICB9XG5cbiAgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT09ICdkYXJ3aW4nKSB7XG4gICAgcmV0dXJuIGBvcGVuIFwiJHt1cml9XCJgO1xuICB9XG5cbiAgcmV0dXJuIGB4ZGctb3BlbiBcIiR7dXJpfVwiYDtcbn1cbiJdLAogICJtYXBwaW5ncyI6ICJBQVdBLFNBQVMsa0JBQWtCO0FBQzNCLE9BQU8sYUFBYTtBQU9wQixTQUFTLFlBQVk7QUFDckIsU0FBUyxtQ0FBbUM7QUFDNUMsU0FBUyx5QkFBeUI7QUFDbEM7QUFBQSxFQUNFO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxPQUNLO0FBRVAsTUFBTSxZQUFZO0FBQ2xCLE1BQU0sMEJBQTBCO0FBQ2hDLE1BQU0sOEJBQThCO0FBQ3BDLE1BQU0sd0JBQXdCO0FBMkU5QixlQUFzQixlQUNwQixRQUNpQjtBQUVqQixRQUFNLEVBQUUsT0FBTyxDQUFDLEdBQUcsV0FBVyxJQUFJLDRCQUE0QixPQUFPLFVBQVUsSUFBSTtBQUNuRixRQUFNLE1BQU0sYUFBYSxRQUFRLElBQUk7QUFHckMsTUFBSSxjQUFjLFVBQWEsQ0FBQyxXQUFXLFNBQVMsR0FBRztBQUNyRCxVQUFNLElBQUksTUFBTSw4QkFBOEIsU0FBUyxFQUFFO0FBQUEsRUFDM0Q7QUFFQSxNQUFJLENBQUMsMkJBQTJCO0FBRTlCLFFBQUksQ0FBQyxrQkFBa0IsR0FBRyxHQUFHO0FBQzNCLFlBQU0sSUFBSTtBQUFBLFFBQ1Isd0NBQXdDLEdBQUc7QUFBQSxNQUM3QztBQUFBLElBQ0Y7QUFHQSxRQUFJLENBQUMsYUFBYSxHQUFHO0FBQ25CLFlBQU0sSUFBSSxNQUFNLHFGQUFxRjtBQUFBLElBQ3ZHO0FBR0EsVUFBTSwyQkFBMkI7QUFBQSxFQUNuQztBQUVBLFFBQU0sY0FBYztBQUNwQixRQUFNLGVBQWUsT0FBTyxLQUFLLE9BQU8sQ0FBQyxFQUFFLE1BQU0sV0FBVztBQUM1RCxRQUFNLGNBQWMsWUFDaEIsMENBQTBDLE9BQU8sU0FBUyxDQUFDLGVBQzNEO0FBQ0osUUFBTSxhQUFhO0FBQUE7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
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
*
|
|
4
|
+
* Reads and queries Obsidian's local configuration (`obsidian.json`).
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Returns the hex vault ID for a given vault path from Obsidian's registry.
|
|
8
|
+
*
|
|
9
|
+
* @param vaultPath - The absolute path to the vault folder.
|
|
10
|
+
* @returns The vault ID, or `undefined` if the vault is not registered.
|
|
11
|
+
*/
|
|
12
|
+
export declare function getVaultId(vaultPath: string): string | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* Checks whether the Obsidian CLI is enabled in Obsidian's settings.
|
|
15
|
+
*
|
|
16
|
+
* @returns `true` if the CLI is enabled, `false` otherwise.
|
|
17
|
+
*/
|
|
18
|
+
export declare function isCliEnabled(): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Checks whether a vault path is registered in Obsidian's vault registry.
|
|
21
|
+
*
|
|
22
|
+
* @param vaultPath - The absolute path to the vault folder.
|
|
23
|
+
* @returns `true` if the vault is registered, `false` otherwise.
|
|
24
|
+
*/
|
|
25
|
+
export declare function isVaultRegistered(vaultPath: string): boolean;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import {
|
|
4
|
+
join,
|
|
5
|
+
resolve
|
|
6
|
+
} from "node:path";
|
|
7
|
+
import process from "node:process";
|
|
8
|
+
function getVaultId(vaultPath) {
|
|
9
|
+
const config = readObsidianJson();
|
|
10
|
+
if (!config) {
|
|
11
|
+
return void 0;
|
|
12
|
+
}
|
|
13
|
+
const normalizedTarget = normalizePath(vaultPath);
|
|
14
|
+
for (const [id, entry] of Object.entries(config.vaults)) {
|
|
15
|
+
if (normalizePath(entry.path) === normalizedTarget) {
|
|
16
|
+
return id;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return void 0;
|
|
20
|
+
}
|
|
21
|
+
function isCliEnabled() {
|
|
22
|
+
const config = readObsidianJson();
|
|
23
|
+
return config?.cli === true;
|
|
24
|
+
}
|
|
25
|
+
function isVaultRegistered(vaultPath) {
|
|
26
|
+
return getVaultId(vaultPath) !== void 0;
|
|
27
|
+
}
|
|
28
|
+
function getObsidianConfigDir() {
|
|
29
|
+
if (process.platform === "win32") {
|
|
30
|
+
const appData = process.env["APPDATA"];
|
|
31
|
+
if (appData) {
|
|
32
|
+
return join(appData, "obsidian");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (process.platform === "darwin") {
|
|
36
|
+
return join(homedir(), "Library", "Application Support", "obsidian");
|
|
37
|
+
}
|
|
38
|
+
return join(process.env["XDG_CONFIG_HOME"] ?? join(homedir(), ".config"), "obsidian");
|
|
39
|
+
}
|
|
40
|
+
function normalizePath(vaultPath) {
|
|
41
|
+
const resolved = resolve(vaultPath);
|
|
42
|
+
return process.platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
43
|
+
}
|
|
44
|
+
function readObsidianJson() {
|
|
45
|
+
const configPath = join(getObsidianConfigDir(), "obsidian.json");
|
|
46
|
+
try {
|
|
47
|
+
const content = readFileSync(configPath, "utf-8");
|
|
48
|
+
return JSON.parse(content);
|
|
49
|
+
} catch {
|
|
50
|
+
return void 0;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export {
|
|
54
|
+
getVaultId,
|
|
55
|
+
isCliEnabled,
|
|
56
|
+
isVaultRegistered
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL29ic2lkaWFuLWNvbmZpZy50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAcGFja2FnZURvY3VtZW50YXRpb25cbiAqXG4gKiBSZWFkcyBhbmQgcXVlcmllcyBPYnNpZGlhbidzIGxvY2FsIGNvbmZpZ3VyYXRpb24gKGBvYnNpZGlhbi5qc29uYCkuXG4gKi9cblxuaW1wb3J0IHsgcmVhZEZpbGVTeW5jIH0gZnJvbSAnbm9kZTpmcyc7XG5pbXBvcnQgeyBob21lZGlyIH0gZnJvbSAnbm9kZTpvcyc7XG5pbXBvcnQge1xuICBqb2luLFxuICByZXNvbHZlXG59IGZyb20gJ25vZGU6cGF0aCc7XG5pbXBvcnQgcHJvY2VzcyBmcm9tICdub2RlOnByb2Nlc3MnO1xuXG4vKipcbiAqIFRoZSB0b3AtbGV2ZWwgc3RydWN0dXJlIG9mIE9ic2lkaWFuJ3MgYG9ic2lkaWFuLmpzb25gIGNvbmZpZyBmaWxlLlxuICovXG5pbnRlcmZhY2UgT2JzaWRpYW5Kc29uIHtcbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIENMSSBpcyBlbmFibGVkIGluIE9ic2lkaWFuIHNldHRpbmdzLlxuICAgKi9cbiAgY2xpPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogTWFwIG9mIHZhdWx0IElEcyB0byB2YXVsdCBlbnRyaWVzLlxuICAgKi9cbiAgdmF1bHRzOiBSZWNvcmQ8c3RyaW5nLCBPYnNpZGlhblZhdWx0RW50cnk+O1xufVxuXG4vKipcbiAqIEEgc2luZ2xlIHZhdWx0IGVudHJ5IGluIGBvYnNpZGlhbi5qc29uYC5cbiAqL1xuaW50ZXJmYWNlIE9ic2lkaWFuVmF1bHRFbnRyeSB7XG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSB2YXVsdCBpcyBjdXJyZW50bHkgb3Blbi5cbiAgICovXG4gIG9wZW4/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaGUgYWJzb2x1dGUgcGF0aCB0byB0aGUgdmF1bHQgZm9sZGVyLlxuICAgKi9cbiAgcGF0aDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaW1lc3RhbXAgb2YgdGhlIGxhc3QgYWNjZXNzLlxuICAgKi9cbiAgdHM6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBoZXggdmF1bHQgSUQgZm9yIGEgZ2l2ZW4gdmF1bHQgcGF0aCBmcm9tIE9ic2lkaWFuJ3MgcmVnaXN0cnkuXG4gKlxuICogQHBhcmFtIHZhdWx0UGF0aCAtIFRoZSBhYnNvbHV0ZSBwYXRoIHRvIHRoZSB2YXVsdCBmb2xkZXIuXG4gKiBAcmV0dXJucyBUaGUgdmF1bHQgSUQsIG9yIGB1bmRlZmluZWRgIGlmIHRoZSB2YXVsdCBpcyBub3QgcmVnaXN0ZXJlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFZhdWx0SWQodmF1bHRQYXRoOiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb25zdCBjb25maWcgPSByZWFkT2JzaWRpYW5Kc29uKCk7XG4gIGlmICghY29uZmlnKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIGNvbnN0IG5vcm1hbGl6ZWRUYXJnZXQgPSBub3JtYWxpemVQYXRoKHZhdWx0UGF0aCk7XG5cbiAgZm9yIChjb25zdCBbaWQsIGVudHJ5XSBvZiBPYmplY3QuZW50cmllcyhjb25maWcudmF1bHRzKSkge1xuICAgIGlmIChub3JtYWxpemVQYXRoKGVudHJ5LnBhdGgpID09PSBub3JtYWxpemVkVGFyZ2V0KSB7XG4gICAgICByZXR1cm4gaWQ7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciB0aGUgT2JzaWRpYW4gQ0xJIGlzIGVuYWJsZWQgaW4gT2JzaWRpYW4ncyBzZXR0aW5ncy5cbiAqXG4gKiBAcmV0dXJucyBgdHJ1ZWAgaWYgdGhlIENMSSBpcyBlbmFibGVkLCBgZmFsc2VgIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzQ2xpRW5hYmxlZCgpOiBib29sZWFuIHtcbiAgY29uc3QgY29uZmlnID0gcmVhZE9ic2lkaWFuSnNvbigpO1xuICByZXR1cm4gY29uZmlnPy5jbGkgPT09IHRydWU7XG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYSB2YXVsdCBwYXRoIGlzIHJlZ2lzdGVyZWQgaW4gT2JzaWRpYW4ncyB2YXVsdCByZWdpc3RyeS5cbiAqXG4gKiBAcGFyYW0gdmF1bHRQYXRoIC0gVGhlIGFic29sdXRlIHBhdGggdG8gdGhlIHZhdWx0IGZvbGRlci5cbiAqIEByZXR1cm5zIGB0cnVlYCBpZiB0aGUgdmF1bHQgaXMgcmVnaXN0ZXJlZCwgYGZhbHNlYCBvdGhlcndpc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1ZhdWx0UmVnaXN0ZXJlZCh2YXVsdFBhdGg6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gZ2V0VmF1bHRJZCh2YXVsdFBhdGgpICE9PSB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgcGxhdGZvcm0tc3BlY2lmaWMgcGF0aCB0byBPYnNpZGlhbidzIGNvbmZpZyBkaXJlY3RvcnkuXG4gKlxuICogQHJldHVybnMgVGhlIGFic29sdXRlIHBhdGggdG8gdGhlIGBvYnNpZGlhbi9gIGNvbmZpZyBkaXJlY3RvcnkuXG4gKi9cbmZ1bmN0aW9uIGdldE9ic2lkaWFuQ29uZmlnRGlyKCk6IHN0cmluZyB7XG4gIGlmIChwcm9jZXNzLnBsYXRmb3JtID09PSAnd2luMzInKSB7XG4gICAgY29uc3QgYXBwRGF0YSA9IHByb2Nlc3MuZW52WydBUFBEQVRBJ107XG4gICAgaWYgKGFwcERhdGEpIHtcbiAgICAgIHJldHVybiBqb2luKGFwcERhdGEsICdvYnNpZGlhbicpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChwcm9jZXNzLnBsYXRmb3JtID09PSAnZGFyd2luJykge1xuICAgIHJldHVybiBqb2luKGhvbWVkaXIoKSwgJ0xpYnJhcnknLCAnQXBwbGljYXRpb24gU3VwcG9ydCcsICdvYnNpZGlhbicpO1xuICB9XG5cbiAgcmV0dXJuIGpvaW4ocHJvY2Vzcy5lbnZbJ1hER19DT05GSUdfSE9NRSddID8/IGpvaW4oaG9tZWRpcigpLCAnLmNvbmZpZycpLCAnb2JzaWRpYW4nKTtcbn1cblxuLyoqXG4gKiBOb3JtYWxpemVzIGEgdmF1bHQgcGF0aCBmb3IgY29tcGFyaXNvbi5cbiAqIE9uIFdpbmRvd3MsIHBhdGhzIGFyZSBjYXNlLWluc2Vuc2l0aXZlIGFuZCBzZXBhcmF0b3JzIG1heSB2YXJ5LlxuICpcbiAqIEBwYXJhbSB2YXVsdFBhdGggLSBUaGUgcGF0aCB0byBub3JtYWxpemUuXG4gKiBAcmV0dXJucyBUaGUgbm9ybWFsaXplZCBwYXRoLlxuICovXG5mdW5jdGlvbiBub3JtYWxpemVQYXRoKHZhdWx0UGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgcmVzb2x2ZWQgPSByZXNvbHZlKHZhdWx0UGF0aCk7XG4gIHJldHVybiBwcm9jZXNzLnBsYXRmb3JtID09PSAnd2luMzInID8gcmVzb2x2ZWQudG9Mb3dlckNhc2UoKSA6IHJlc29sdmVkO1xufVxuXG4vKipcbiAqIFJlYWRzIGFuZCBwYXJzZXMgT2JzaWRpYW4ncyBgb2JzaWRpYW4uanNvbmAgY29uZmlnIGZpbGUuXG4gKlxuICogQHJldHVybnMgVGhlIHBhcnNlZCBjb25maWcsIG9yIGB1bmRlZmluZWRgIGlmIHRoZSBmaWxlIGRvZXNuJ3QgZXhpc3Qgb3IgY2FuJ3QgYmUgcGFyc2VkLlxuICovXG5mdW5jdGlvbiByZWFkT2JzaWRpYW5Kc29uKCk6IE9ic2lkaWFuSnNvbiB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IGNvbmZpZ1BhdGggPSBqb2luKGdldE9ic2lkaWFuQ29uZmlnRGlyKCksICdvYnNpZGlhbi5qc29uJyk7XG4gIHRyeSB7XG4gICAgY29uc3QgY29udGVudCA9IHJlYWRGaWxlU3luYyhjb25maWdQYXRoLCAndXRmLTgnKTtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShjb250ZW50KSBhcyBPYnNpZGlhbkpzb247XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cbiJdLAogICJtYXBwaW5ncyI6ICJBQU1BLFNBQVMsb0JBQW9CO0FBQzdCLFNBQVMsZUFBZTtBQUN4QjtBQUFBLEVBQ0U7QUFBQSxFQUNBO0FBQUEsT0FDSztBQUNQLE9BQU8sYUFBYTtBQTJDYixTQUFTLFdBQVcsV0FBdUM7QUFDaEUsUUFBTSxTQUFTLGlCQUFpQjtBQUNoQyxNQUFJLENBQUMsUUFBUTtBQUNYLFdBQU87QUFBQSxFQUNUO0FBRUEsUUFBTSxtQkFBbUIsY0FBYyxTQUFTO0FBRWhELGFBQVcsQ0FBQyxJQUFJLEtBQUssS0FBSyxPQUFPLFFBQVEsT0FBTyxNQUFNLEdBQUc7QUFDdkQsUUFBSSxjQUFjLE1BQU0sSUFBSSxNQUFNLGtCQUFrQjtBQUNsRCxhQUFPO0FBQUEsSUFDVDtBQUFBLEVBQ0Y7QUFFQSxTQUFPO0FBQ1Q7QUFPTyxTQUFTLGVBQXdCO0FBQ3RDLFFBQU0sU0FBUyxpQkFBaUI7QUFDaEMsU0FBTyxRQUFRLFFBQVE7QUFDekI7QUFRTyxTQUFTLGtCQUFrQixXQUE0QjtBQUM1RCxTQUFPLFdBQVcsU0FBUyxNQUFNO0FBQ25DO0FBT0EsU0FBUyx1QkFBK0I7QUFDdEMsTUFBSSxRQUFRLGFBQWEsU0FBUztBQUNoQyxVQUFNLFVBQVUsUUFBUSxJQUFJLFNBQVM7QUFDckMsUUFBSSxTQUFTO0FBQ1gsYUFBTyxLQUFLLFNBQVMsVUFBVTtBQUFBLElBQ2pDO0FBQUEsRUFDRjtBQUVBLE1BQUksUUFBUSxhQUFhLFVBQVU7QUFDakMsV0FBTyxLQUFLLFFBQVEsR0FBRyxXQUFXLHVCQUF1QixVQUFVO0FBQUEsRUFDckU7QUFFQSxTQUFPLEtBQUssUUFBUSxJQUFJLGlCQUFpQixLQUFLLEtBQUssUUFBUSxHQUFHLFNBQVMsR0FBRyxVQUFVO0FBQ3RGO0FBU0EsU0FBUyxjQUFjLFdBQTJCO0FBQ2hELFFBQU0sV0FBVyxRQUFRLFNBQVM7QUFDbEMsU0FBTyxRQUFRLGFBQWEsVUFBVSxTQUFTLFlBQVksSUFBSTtBQUNqRTtBQU9BLFNBQVMsbUJBQTZDO0FBQ3BELFFBQU0sYUFBYSxLQUFLLHFCQUFxQixHQUFHLGVBQWU7QUFDL0QsTUFBSTtBQUNGLFVBQU0sVUFBVSxhQUFhLFlBQVksT0FBTztBQUNoRCxXQUFPLEtBQUssTUFBTSxPQUFPO0FBQUEsRUFDM0IsUUFBUTtBQUNOLFdBQU87QUFBQSxFQUNUO0FBQ0Y7IiwKICAibmFtZXMiOiBbXQp9Cg==
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parameters for the {@link TempVault} constructor.
|
|
3
|
+
*/
|
|
4
|
+
export interface TempVaultParams {
|
|
5
|
+
/**
|
|
6
|
+
* Map of file paths to content. Parent directories are created automatically.
|
|
7
|
+
*
|
|
8
|
+
* To create an empty folder, use a path ending with `/` and an empty string as content.
|
|
9
|
+
*/
|
|
10
|
+
files?: Record<string, string>;
|
|
11
|
+
/**
|
|
12
|
+
* An explicit vault path. If omitted, a temp directory is created.
|
|
13
|
+
*/
|
|
14
|
+
path?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A temporary Obsidian vault for integration tests.
|
|
18
|
+
*
|
|
19
|
+
* Creates a temp directory and registers it in the running Obsidian instance
|
|
20
|
+
* so that the Obsidian CLI can target it via `cwd`.
|
|
21
|
+
*/
|
|
22
|
+
export declare class TempVault {
|
|
23
|
+
/**
|
|
24
|
+
* The absolute path to the temporary vault.
|
|
25
|
+
*/
|
|
26
|
+
readonly path: string;
|
|
27
|
+
/**
|
|
28
|
+
* Creates a new temp vault, optionally pre-populated with files.
|
|
29
|
+
*
|
|
30
|
+
* @param params - Configuration for the vault.
|
|
31
|
+
*/
|
|
32
|
+
constructor(params?: TempVaultParams);
|
|
33
|
+
/**
|
|
34
|
+
* Unregisters the vault from Obsidian and deletes the temp directory.
|
|
35
|
+
*/
|
|
36
|
+
dispose(): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Registers this vault in the running Obsidian instance so the CLI can target it.
|
|
39
|
+
*/
|
|
40
|
+
register(): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Async disposable support for `await using`.
|
|
43
|
+
*
|
|
44
|
+
* @returns A promise that resolves when the vault is disposed.
|
|
45
|
+
*/
|
|
46
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
47
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import {
|
|
2
|
+
mkdirSync,
|
|
3
|
+
mkdtempSync,
|
|
4
|
+
writeFileSync
|
|
5
|
+
} from "node:fs";
|
|
6
|
+
import { rm } from "node:fs/promises";
|
|
7
|
+
import { tmpdir } from "node:os";
|
|
8
|
+
import {
|
|
9
|
+
dirname,
|
|
10
|
+
join
|
|
11
|
+
} from "node:path";
|
|
12
|
+
import {
|
|
13
|
+
registerVault,
|
|
14
|
+
unregisterVault
|
|
15
|
+
} from "./vault-registry.mjs";
|
|
16
|
+
const RM_RETRY_DELAY_MS = 500;
|
|
17
|
+
const RM_RETRY_TIMEOUT_MS = 1e4;
|
|
18
|
+
class TempVault {
|
|
19
|
+
/**
|
|
20
|
+
* The absolute path to the temporary vault.
|
|
21
|
+
*/
|
|
22
|
+
path;
|
|
23
|
+
/**
|
|
24
|
+
* Creates a new temp vault, optionally pre-populated with files.
|
|
25
|
+
*
|
|
26
|
+
* @param params - Configuration for the vault.
|
|
27
|
+
*/
|
|
28
|
+
constructor(params = {}) {
|
|
29
|
+
this.path = params.path ?? mkdtempSync(join(tmpdir(), "temp-vault-"));
|
|
30
|
+
for (const [filePath, content] of Object.entries(params.files ?? {})) {
|
|
31
|
+
const fullPath = join(this.path, filePath);
|
|
32
|
+
if (filePath.endsWith("/")) {
|
|
33
|
+
if (content !== "") {
|
|
34
|
+
throw new Error(`Folder path "${filePath}" must have empty content`);
|
|
35
|
+
}
|
|
36
|
+
mkdirSync(fullPath, { recursive: true });
|
|
37
|
+
} else {
|
|
38
|
+
mkdirSync(dirname(fullPath), { recursive: true });
|
|
39
|
+
writeFileSync(fullPath, content);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Unregisters the vault from Obsidian and deletes the temp directory.
|
|
45
|
+
*/
|
|
46
|
+
async dispose() {
|
|
47
|
+
await unregisterVault(this.path);
|
|
48
|
+
await retryRm(this.path);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Registers this vault in the running Obsidian instance so the CLI can target it.
|
|
52
|
+
*/
|
|
53
|
+
async register() {
|
|
54
|
+
await registerVault(this.path);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Async disposable support for `await using`.
|
|
58
|
+
*
|
|
59
|
+
* @returns A promise that resolves when the vault is disposed.
|
|
60
|
+
*/
|
|
61
|
+
async [Symbol.asyncDispose]() {
|
|
62
|
+
return this.dispose();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async function retryRm(path) {
|
|
66
|
+
const deadline = Date.now() + RM_RETRY_TIMEOUT_MS;
|
|
67
|
+
while (Date.now() < deadline) {
|
|
68
|
+
try {
|
|
69
|
+
await rm(path, { force: true, recursive: true });
|
|
70
|
+
return;
|
|
71
|
+
} catch {
|
|
72
|
+
await new Promise((resolve) => {
|
|
73
|
+
setTimeout(resolve, RM_RETRY_DELAY_MS);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
await rm(path, { force: true, recursive: true });
|
|
78
|
+
}
|
|
79
|
+
export {
|
|
80
|
+
TempVault
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3RlbXAtdmF1bHQudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qIHY4IGlnbm9yZSBzdGFydCAtLSBJbnRlZ3JhdGlvbi10aW1lIGNvZGUgY292ZXJlZCBieSBpbnRlZ3JhdGlvbiB0ZXN0cywgbm90IHVuaXQgdGVzdHMuICovXG5cbi8qKlxuICogQHBhY2thZ2VEb2N1bWVudGF0aW9uXG4gKlxuICogTWFuYWdlcyB0ZW1wb3JhcnkgdmF1bHQgbGlmZWN5Y2xlIGZvciBpbnRlZ3JhdGlvbiB0ZXN0cy5cbiAqL1xuXG5pbXBvcnQge1xuICBta2RpclN5bmMsXG4gIG1rZHRlbXBTeW5jLFxuICB3cml0ZUZpbGVTeW5jXG59IGZyb20gJ25vZGU6ZnMnO1xuaW1wb3J0IHsgcm0gfSBmcm9tICdub2RlOmZzL3Byb21pc2VzJztcbmltcG9ydCB7IHRtcGRpciB9IGZyb20gJ25vZGU6b3MnO1xuaW1wb3J0IHtcbiAgZGlybmFtZSxcbiAgam9pblxufSBmcm9tICdub2RlOnBhdGgnO1xuXG5pbXBvcnQge1xuICByZWdpc3RlclZhdWx0LFxuICB1bnJlZ2lzdGVyVmF1bHRcbn0gZnJvbSAnLi92YXVsdC1yZWdpc3RyeS5tanMnO1xuXG4vKipcbiAqIFBhcmFtZXRlcnMgZm9yIHRoZSB7QGxpbmsgVGVtcFZhdWx0fSBjb25zdHJ1Y3Rvci5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUZW1wVmF1bHRQYXJhbXMge1xuICAvKipcbiAgICogTWFwIG9mIGZpbGUgcGF0aHMgdG8gY29udGVudC4gUGFyZW50IGRpcmVjdG9yaWVzIGFyZSBjcmVhdGVkIGF1dG9tYXRpY2FsbHkuXG4gICAqXG4gICAqIFRvIGNyZWF0ZSBhbiBlbXB0eSBmb2xkZXIsIHVzZSBhIHBhdGggZW5kaW5nIHdpdGggYC9gIGFuZCBhbiBlbXB0eSBzdHJpbmcgYXMgY29udGVudC5cbiAgICovXG4gIGZpbGVzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcblxuICAvKipcbiAgICogQW4gZXhwbGljaXQgdmF1bHQgcGF0aC4gSWYgb21pdHRlZCwgYSB0ZW1wIGRpcmVjdG9yeSBpcyBjcmVhdGVkLlxuICAgKi9cbiAgcGF0aD86IHN0cmluZztcbn1cblxuY29uc3QgUk1fUkVUUllfREVMQVlfTVMgPSA1MDA7XG5jb25zdCBSTV9SRVRSWV9USU1FT1VUX01TID0gMTAwMDA7XG5cbi8qKlxuICogQSB0ZW1wb3JhcnkgT2JzaWRpYW4gdmF1bHQgZm9yIGludGVncmF0aW9uIHRlc3RzLlxuICpcbiAqIENyZWF0ZXMgYSB0ZW1wIGRpcmVjdG9yeSBhbmQgcmVnaXN0ZXJzIGl0IGluIHRoZSBydW5uaW5nIE9ic2lkaWFuIGluc3RhbmNlXG4gKiBzbyB0aGF0IHRoZSBPYnNpZGlhbiBDTEkgY2FuIHRhcmdldCBpdCB2aWEgYGN3ZGAuXG4gKi9cbmV4cG9ydCBjbGFzcyBUZW1wVmF1bHQge1xuICAvKipcbiAgICogVGhlIGFic29sdXRlIHBhdGggdG8gdGhlIHRlbXBvcmFyeSB2YXVsdC5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBwYXRoOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgdGVtcCB2YXVsdCwgb3B0aW9uYWxseSBwcmUtcG9wdWxhdGVkIHdpdGggZmlsZXMuXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBDb25maWd1cmF0aW9uIGZvciB0aGUgdmF1bHQuXG4gICAqL1xuICBwdWJsaWMgY29uc3RydWN0b3IocGFyYW1zOiBUZW1wVmF1bHRQYXJhbXMgPSB7fSkge1xuICAgIHRoaXMucGF0aCA9IHBhcmFtcy5wYXRoID8/IG1rZHRlbXBTeW5jKGpvaW4odG1wZGlyKCksICd0ZW1wLXZhdWx0LScpKTtcblxuICAgIGZvciAoY29uc3QgW2ZpbGVQYXRoLCBjb250ZW50XSBvZiBPYmplY3QuZW50cmllcyhwYXJhbXMuZmlsZXMgPz8ge30pKSB7XG4gICAgICBjb25zdCBmdWxsUGF0aCA9IGpvaW4odGhpcy5wYXRoLCBmaWxlUGF0aCk7XG4gICAgICBpZiAoZmlsZVBhdGguZW5kc1dpdGgoJy8nKSkge1xuICAgICAgICBpZiAoY29udGVudCAhPT0gJycpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEZvbGRlciBwYXRoIFwiJHtmaWxlUGF0aH1cIiBtdXN0IGhhdmUgZW1wdHkgY29udGVudGApO1xuICAgICAgICB9XG4gICAgICAgIG1rZGlyU3luYyhmdWxsUGF0aCwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBta2RpclN5bmMoZGlybmFtZShmdWxsUGF0aCksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgICAgICB3cml0ZUZpbGVTeW5jKGZ1bGxQYXRoLCBjb250ZW50KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVW5yZWdpc3RlcnMgdGhlIHZhdWx0IGZyb20gT2JzaWRpYW4gYW5kIGRlbGV0ZXMgdGhlIHRlbXAgZGlyZWN0b3J5LlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGRpc3Bvc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdW5yZWdpc3RlclZhdWx0KHRoaXMucGF0aCk7XG4gICAgYXdhaXQgcmV0cnlSbSh0aGlzLnBhdGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyB0aGlzIHZhdWx0IGluIHRoZSBydW5uaW5nIE9ic2lkaWFuIGluc3RhbmNlIHNvIHRoZSBDTEkgY2FuIHRhcmdldCBpdC5cbiAgICovXG4gIHB1YmxpYyBhc3luYyByZWdpc3RlcigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCByZWdpc3RlclZhdWx0KHRoaXMucGF0aCk7XG4gIH1cblxuICAvKipcbiAgICogQXN5bmMgZGlzcG9zYWJsZSBzdXBwb3J0IGZvciBgYXdhaXQgdXNpbmdgLlxuICAgKlxuICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSB2YXVsdCBpcyBkaXNwb3NlZC5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBbU3ltYm9sLmFzeW5jRGlzcG9zZV0oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuZGlzcG9zZSgpO1xuICB9XG59XG5cbi8qKlxuICogUmV0cmllcyBgcm1gIHVudGlsIGl0IHN1Y2NlZWRzIG9yIHRpbWVzIG91dC5cbiAqIE9ic2lkaWFuIG1heSBob2xkIGZpbGUgbG9ja3MgYnJpZWZseSBhZnRlciBhIHdpbmRvdyBpcyBkZXN0cm95ZWQuXG4gKlxuICogQHBhcmFtIHBhdGggLSBUaGUgcGF0aCB0byB0aGUgZGlyZWN0b3J5IHRvIHJlbW92ZS5cbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIGRpcmVjdG9yeSBpcyByZW1vdmVkLlxuICovXG5hc3luYyBmdW5jdGlvbiByZXRyeVJtKHBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBkZWFkbGluZSA9IERhdGUubm93KCkgKyBSTV9SRVRSWV9USU1FT1VUX01TO1xuICB3aGlsZSAoRGF0ZS5ub3coKSA8IGRlYWRsaW5lKSB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHJtKHBhdGgsIHsgZm9yY2U6IHRydWUsIHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9IGNhdGNoIHtcbiAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICAgIHNldFRpbWVvdXQocmVzb2x2ZSwgUk1fUkVUUllfREVMQVlfTVMpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG4gIC8vIEZpbmFsIGF0dGVtcHQgXHUyMDE0IGxldCBpdCB0aHJvdy5cbiAgYXdhaXQgcm0ocGF0aCwgeyBmb3JjZTogdHJ1ZSwgcmVjdXJzaXZlOiB0cnVlIH0pO1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIkFBUUE7QUFBQSxFQUNFO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxPQUNLO0FBQ1AsU0FBUyxVQUFVO0FBQ25CLFNBQVMsY0FBYztBQUN2QjtBQUFBLEVBQ0U7QUFBQSxFQUNBO0FBQUEsT0FDSztBQUVQO0FBQUEsRUFDRTtBQUFBLEVBQ0E7QUFBQSxPQUNLO0FBbUJQLE1BQU0sb0JBQW9CO0FBQzFCLE1BQU0sc0JBQXNCO0FBUXJCLE1BQU0sVUFBVTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBSUw7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFPVCxZQUFZLFNBQTBCLENBQUMsR0FBRztBQUMvQyxTQUFLLE9BQU8sT0FBTyxRQUFRLFlBQVksS0FBSyxPQUFPLEdBQUcsYUFBYSxDQUFDO0FBRXBFLGVBQVcsQ0FBQyxVQUFVLE9BQU8sS0FBSyxPQUFPLFFBQVEsT0FBTyxTQUFTLENBQUMsQ0FBQyxHQUFHO0FBQ3BFLFlBQU0sV0FBVyxLQUFLLEtBQUssTUFBTSxRQUFRO0FBQ3pDLFVBQUksU0FBUyxTQUFTLEdBQUcsR0FBRztBQUMxQixZQUFJLFlBQVksSUFBSTtBQUNsQixnQkFBTSxJQUFJLE1BQU0sZ0JBQWdCLFFBQVEsMkJBQTJCO0FBQUEsUUFDckU7QUFDQSxrQkFBVSxVQUFVLEVBQUUsV0FBVyxLQUFLLENBQUM7QUFBQSxNQUN6QyxPQUFPO0FBQ0wsa0JBQVUsUUFBUSxRQUFRLEdBQUcsRUFBRSxXQUFXLEtBQUssQ0FBQztBQUNoRCxzQkFBYyxVQUFVLE9BQU87QUFBQSxNQUNqQztBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFLQSxNQUFhLFVBQXlCO0FBQ3BDLFVBQU0sZ0JBQWdCLEtBQUssSUFBSTtBQUMvQixVQUFNLFFBQVEsS0FBSyxJQUFJO0FBQUEsRUFDekI7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQUtBLE1BQWEsV0FBMEI7QUFDckMsVUFBTSxjQUFjLEtBQUssSUFBSTtBQUFBLEVBQy9CO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBT0EsT0FBYyxPQUFPLFlBQVksSUFBbUI7QUFDbEQsV0FBTyxLQUFLLFFBQVE7QUFBQSxFQUN0QjtBQUNGO0FBU0EsZUFBZSxRQUFRLE1BQTZCO0FBQ2xELFFBQU0sV0FBVyxLQUFLLElBQUksSUFBSTtBQUM5QixTQUFPLEtBQUssSUFBSSxJQUFJLFVBQVU7QUFDNUIsUUFBSTtBQUNGLFlBQU0sR0FBRyxNQUFNLEVBQUUsT0FBTyxNQUFNLFdBQVcsS0FBSyxDQUFDO0FBQy9DO0FBQUEsSUFDRixRQUFRO0FBQ04sWUFBTSxJQUFJLFFBQVEsQ0FBQyxZQUFZO0FBQzdCLG1CQUFXLFNBQVMsaUJBQWlCO0FBQUEsTUFDdkMsQ0FBQztBQUFBLElBQ0g7QUFBQSxFQUNGO0FBRUEsUUFBTSxHQUFHLE1BQU0sRUFBRSxPQUFPLE1BQU0sV0FBVyxLQUFLLENBQUM7QUFDakQ7IiwKICAibmFtZXMiOiBbXQp9Cg==
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
*
|
|
4
|
+
* Contains utility functions for type guards.
|
|
5
|
+
*/
|
|
6
|
+
type NullableConstraint<T> = null extends T ? unknown : undefined extends T ? unknown : never;
|
|
7
|
+
/**
|
|
8
|
+
* Asserts that a value is not `null` or `undefined`, narrowing its type in place.
|
|
9
|
+
*
|
|
10
|
+
* Only callable when `T` includes `null` or `undefined`. Passing an already non-nullable type is a compile error.
|
|
11
|
+
*
|
|
12
|
+
* @typeParam T - The type of the value.
|
|
13
|
+
* @param value - The value to check.
|
|
14
|
+
* @param errorOrMessage - Optional {@link Error} or error message string.
|
|
15
|
+
* @throws If the value is `null` or `undefined`.
|
|
16
|
+
*/
|
|
17
|
+
export declare function assertNonNullable<T extends NullableConstraint<T>>(value: T, errorOrMessage?: Error | string): asserts value is NonNullable<T>;
|
|
18
|
+
/**
|
|
19
|
+
* Ensures that a value is not `null` or `undefined` and returns it with narrowed type.
|
|
20
|
+
*
|
|
21
|
+
* Only callable when `T` includes `null` or `undefined`. Passing an already non-nullable type is a compile error.
|
|
22
|
+
*
|
|
23
|
+
* @typeParam T - The type of the value.
|
|
24
|
+
* @param value - The value to check.
|
|
25
|
+
* @param errorOrMessage - Optional {@link Error} or error message string.
|
|
26
|
+
* @returns The value with `null` and `undefined` excluded from its type.
|
|
27
|
+
* @throws If the value is `null` or `undefined`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function ensureNonNullable<T extends NullableConstraint<T>>(value: T, errorOrMessage?: Error | string): NonNullable<T>;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
function assertNonNullable(value, errorOrMessage) {
|
|
2
|
+
if (value !== null && value !== void 0) {
|
|
3
|
+
return;
|
|
4
|
+
}
|
|
5
|
+
errorOrMessage ??= value === null ? "Value is null" : "Value is undefined";
|
|
6
|
+
const error = typeof errorOrMessage === "string" ? new Error(errorOrMessage) : errorOrMessage;
|
|
7
|
+
throw error;
|
|
8
|
+
}
|
|
9
|
+
function ensureNonNullable(value, errorOrMessage) {
|
|
10
|
+
assertNonNullable(value, errorOrMessage);
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
assertNonNullable,
|
|
15
|
+
ensureNonNullable
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3R5cGUtZ3VhcmRzLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuICpcbiAqIENvbnRhaW5zIHV0aWxpdHkgZnVuY3Rpb25zIGZvciB0eXBlIGd1YXJkcy5cbiAqL1xuXG50eXBlIE51bGxhYmxlQ29uc3RyYWludDxUPiA9IG51bGwgZXh0ZW5kcyBUID8gdW5rbm93biA6IHVuZGVmaW5lZCBleHRlbmRzIFQgPyB1bmtub3duIDogbmV2ZXI7XG5cbi8qKlxuICogQXNzZXJ0cyB0aGF0IGEgdmFsdWUgaXMgbm90IGBudWxsYCBvciBgdW5kZWZpbmVkYCwgbmFycm93aW5nIGl0cyB0eXBlIGluIHBsYWNlLlxuICpcbiAqIE9ubHkgY2FsbGFibGUgd2hlbiBgVGAgaW5jbHVkZXMgYG51bGxgIG9yIGB1bmRlZmluZWRgLiBQYXNzaW5nIGFuIGFscmVhZHkgbm9uLW51bGxhYmxlIHR5cGUgaXMgYSBjb21waWxlIGVycm9yLlxuICpcbiAqIEB0eXBlUGFyYW0gVCAtIFRoZSB0eXBlIG9mIHRoZSB2YWx1ZS5cbiAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEBwYXJhbSBlcnJvck9yTWVzc2FnZSAtIE9wdGlvbmFsIHtAbGluayBFcnJvcn0gb3IgZXJyb3IgbWVzc2FnZSBzdHJpbmcuXG4gKiBAdGhyb3dzIElmIHRoZSB2YWx1ZSBpcyBgbnVsbGAgb3IgYHVuZGVmaW5lZGAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhc3NlcnROb25OdWxsYWJsZTxUIGV4dGVuZHMgTnVsbGFibGVDb25zdHJhaW50PFQ+Pih2YWx1ZTogVCwgZXJyb3JPck1lc3NhZ2U/OiBFcnJvciB8IHN0cmluZyk6IGFzc2VydHMgdmFsdWUgaXMgTm9uTnVsbGFibGU8VD4ge1xuICBpZiAodmFsdWUgIT09IG51bGwgJiYgdmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGVycm9yT3JNZXNzYWdlID8/PSB2YWx1ZSA9PT0gbnVsbCA/ICdWYWx1ZSBpcyBudWxsJyA6ICdWYWx1ZSBpcyB1bmRlZmluZWQnO1xuICBjb25zdCBlcnJvciA9IHR5cGVvZiBlcnJvck9yTWVzc2FnZSA9PT0gJ3N0cmluZycgPyBuZXcgRXJyb3IoZXJyb3JPck1lc3NhZ2UpIDogZXJyb3JPck1lc3NhZ2U7XG4gIHRocm93IGVycm9yO1xufVxuXG4vKipcbiAqIEVuc3VyZXMgdGhhdCBhIHZhbHVlIGlzIG5vdCBgbnVsbGAgb3IgYHVuZGVmaW5lZGAgYW5kIHJldHVybnMgaXQgd2l0aCBuYXJyb3dlZCB0eXBlLlxuICpcbiAqIE9ubHkgY2FsbGFibGUgd2hlbiBgVGAgaW5jbHVkZXMgYG51bGxgIG9yIGB1bmRlZmluZWRgLiBQYXNzaW5nIGFuIGFscmVhZHkgbm9uLW51bGxhYmxlIHR5cGUgaXMgYSBjb21waWxlIGVycm9yLlxuICpcbiAqIEB0eXBlUGFyYW0gVCAtIFRoZSB0eXBlIG9mIHRoZSB2YWx1ZS5cbiAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEBwYXJhbSBlcnJvck9yTWVzc2FnZSAtIE9wdGlvbmFsIHtAbGluayBFcnJvcn0gb3IgZXJyb3IgbWVzc2FnZSBzdHJpbmcuXG4gKiBAcmV0dXJucyBUaGUgdmFsdWUgd2l0aCBgbnVsbGAgYW5kIGB1bmRlZmluZWRgIGV4Y2x1ZGVkIGZyb20gaXRzIHR5cGUuXG4gKiBAdGhyb3dzIElmIHRoZSB2YWx1ZSBpcyBgbnVsbGAgb3IgYHVuZGVmaW5lZGAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbnN1cmVOb25OdWxsYWJsZTxUIGV4dGVuZHMgTnVsbGFibGVDb25zdHJhaW50PFQ+Pih2YWx1ZTogVCwgZXJyb3JPck1lc3NhZ2U/OiBFcnJvciB8IHN0cmluZyk6IE5vbk51bGxhYmxlPFQ+IHtcbiAgYXNzZXJ0Tm9uTnVsbGFibGUodmFsdWUsIGVycm9yT3JNZXNzYWdlKTtcbiAgcmV0dXJuIHZhbHVlO1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIkFBa0JPLFNBQVMsa0JBQW1ELE9BQVUsZ0JBQWtFO0FBQzdJLE1BQUksVUFBVSxRQUFRLFVBQVUsUUFBVztBQUN6QztBQUFBLEVBQ0Y7QUFFQSxxQkFBbUIsVUFBVSxPQUFPLGtCQUFrQjtBQUN0RCxRQUFNLFFBQVEsT0FBTyxtQkFBbUIsV0FBVyxJQUFJLE1BQU0sY0FBYyxJQUFJO0FBQy9FLFFBQU07QUFDUjtBQWFPLFNBQVMsa0JBQW1ELE9BQVUsZ0JBQWlEO0FBQzVILG9CQUFrQixPQUFPLGNBQWM7QUFDdkMsU0FBTztBQUNUOyIsCiAgIm5hbWVzIjogW10KfQo=
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registers a vault path in the running Obsidian instance so the CLI can target it via `cwd`.
|
|
3
|
+
*
|
|
4
|
+
* Uses the `vault-open` IPC to register and open the vault, then polls until
|
|
5
|
+
* the vault's CLI is ready and `getBasePath()` matches `vaultPath`.
|
|
6
|
+
*
|
|
7
|
+
* @param vaultPath - The absolute path to the vault folder.
|
|
8
|
+
*/
|
|
9
|
+
export declare function registerVault(vaultPath: string): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* Unregisters a vault path from the running Obsidian instance.
|
|
12
|
+
*
|
|
13
|
+
* Schedules the vault window to close, waits for it, then removes
|
|
14
|
+
* the vault from the registry via `vault-remove` IPC.
|
|
15
|
+
*
|
|
16
|
+
* @param vaultPath - The absolute path to the vault folder.
|
|
17
|
+
*/
|
|
18
|
+
export declare function unregisterVault(vaultPath: string): Promise<void>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { evalInObsidian } from "./obsidian-cli.mjs";
|
|
2
|
+
const POLL_INTERVAL_MS = 500;
|
|
3
|
+
const POLL_TIMEOUT_MS = 3e4;
|
|
4
|
+
const CLOSE_DELAY_MS = 1e3;
|
|
5
|
+
async function registerVault(vaultPath) {
|
|
6
|
+
await evalInObsidian({
|
|
7
|
+
args: { vaultPath },
|
|
8
|
+
// eslint-disable-next-line no-shadow -- No actual shadowing as the function is executed externally.
|
|
9
|
+
fn({ vaultPath: vaultPath2 }) {
|
|
10
|
+
window.electron.ipcRenderer.sendSync("vault-open", vaultPath2, false);
|
|
11
|
+
},
|
|
12
|
+
shouldSkipPreflightChecks: true
|
|
13
|
+
});
|
|
14
|
+
const deadline = Date.now() + POLL_TIMEOUT_MS;
|
|
15
|
+
while (Date.now() < deadline) {
|
|
16
|
+
try {
|
|
17
|
+
const basePath = await evalInObsidian({
|
|
18
|
+
fn({ app }) {
|
|
19
|
+
return app.vault.adapter.getBasePath();
|
|
20
|
+
},
|
|
21
|
+
shouldSkipPreflightChecks: true,
|
|
22
|
+
vaultPath
|
|
23
|
+
});
|
|
24
|
+
if (basePath === vaultPath) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
} catch {
|
|
28
|
+
}
|
|
29
|
+
await new Promise((r) => {
|
|
30
|
+
setTimeout(r, POLL_INTERVAL_MS);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
throw new Error(`Vault at ${vaultPath} did not become ready within ${String(POLL_TIMEOUT_MS)}ms`);
|
|
34
|
+
}
|
|
35
|
+
async function unregisterVault(vaultPath) {
|
|
36
|
+
try {
|
|
37
|
+
await evalInObsidian({
|
|
38
|
+
fn() {
|
|
39
|
+
setTimeout(() => {
|
|
40
|
+
window.electron.remote?.getCurrentWindow().destroy();
|
|
41
|
+
}, 0);
|
|
42
|
+
},
|
|
43
|
+
shouldSkipPreflightChecks: true,
|
|
44
|
+
vaultPath
|
|
45
|
+
});
|
|
46
|
+
} catch {
|
|
47
|
+
}
|
|
48
|
+
await new Promise((r) => {
|
|
49
|
+
setTimeout(r, CLOSE_DELAY_MS);
|
|
50
|
+
});
|
|
51
|
+
await evalInObsidian({
|
|
52
|
+
args: { vaultPath },
|
|
53
|
+
// eslint-disable-next-line no-shadow -- No actual shadowing as the function is executed externally.
|
|
54
|
+
fn({ vaultPath: vaultPath2 }) {
|
|
55
|
+
window.electron.ipcRenderer.sendSync("vault-remove", vaultPath2);
|
|
56
|
+
},
|
|
57
|
+
shouldSkipPreflightChecks: true
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
export {
|
|
61
|
+
registerVault,
|
|
62
|
+
unregisterVault
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3ZhdWx0LXJlZ2lzdHJ5LnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKiB2OCBpZ25vcmUgc3RhcnQgLS0gSW50ZWdyYXRpb24tdGltZSBjb2RlIGNvdmVyZWQgYnkgaW50ZWdyYXRpb24gdGVzdHMsIG5vdCB1bml0IHRlc3RzLiAqL1xuXG4vKipcbiAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuICpcbiAqIE1hbmFnZXMgdmF1bHQgcmVnaXN0cmF0aW9uIGluIHRoZSBydW5uaW5nIE9ic2lkaWFuIGluc3RhbmNlLlxuICovXG5cbmltcG9ydCB0eXBlIHsgRmlsZVN5c3RlbUFkYXB0ZXIgfSBmcm9tICdvYnNpZGlhbic7XG5cbmltcG9ydCB7IGV2YWxJbk9ic2lkaWFuIH0gZnJvbSAnLi9vYnNpZGlhbi1jbGkubWpzJztcblxuY29uc3QgUE9MTF9JTlRFUlZBTF9NUyA9IDUwMDtcbmNvbnN0IFBPTExfVElNRU9VVF9NUyA9IDMwMDAwO1xuY29uc3QgQ0xPU0VfREVMQVlfTVMgPSAxMDAwO1xuXG5pbnRlcmZhY2UgRWxlY3Ryb24ge1xuICByZW1vdGU6IEVsZWN0cm9uUmVtb3RlO1xufVxuXG5pbnRlcmZhY2UgRWxlY3Ryb25SZW1vdGUge1xuICBnZXRDdXJyZW50V2luZG93KCk6IEdldEN1cnJlbnRXaW5kb3dSZXN1bHQ7XG59XG5cbmludGVyZmFjZSBHZXRDdXJyZW50V2luZG93UmVzdWx0IHtcbiAgZGVzdHJveSgpOiB2b2lkO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyBhIHZhdWx0IHBhdGggaW4gdGhlIHJ1bm5pbmcgT2JzaWRpYW4gaW5zdGFuY2Ugc28gdGhlIENMSSBjYW4gdGFyZ2V0IGl0IHZpYSBgY3dkYC5cbiAqXG4gKiBVc2VzIHRoZSBgdmF1bHQtb3BlbmAgSVBDIHRvIHJlZ2lzdGVyIGFuZCBvcGVuIHRoZSB2YXVsdCwgdGhlbiBwb2xscyB1bnRpbFxuICogdGhlIHZhdWx0J3MgQ0xJIGlzIHJlYWR5IGFuZCBgZ2V0QmFzZVBhdGgoKWAgbWF0Y2hlcyBgdmF1bHRQYXRoYC5cbiAqXG4gKiBAcGFyYW0gdmF1bHRQYXRoIC0gVGhlIGFic29sdXRlIHBhdGggdG8gdGhlIHZhdWx0IGZvbGRlci5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlZ2lzdGVyVmF1bHQodmF1bHRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgLy8gT3BlbiB0aGUgdmF1bHQgdmlhIElQQy4gVGhlIHNlbmRTeW5jIHJldHVybiB2YWx1ZSBpcyB1bnJlbGlhYmxlXG4gIC8vIChDTEkgb3V0cHV0IG1heSBiZSBsb3N0IHdoZW4gdGhlIG5ldyB3aW5kb3cgb3BlbnMpLCBzbyB3ZSBpZ25vcmUgaXRcbiAgLy8gQW5kIHBvbGwgZm9yIHJlYWRpbmVzcyBpbnN0ZWFkLlxuICBhd2FpdCBldmFsSW5PYnNpZGlhbih7XG4gICAgYXJnczogeyB2YXVsdFBhdGggfSxcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tc2hhZG93IC0tIE5vIGFjdHVhbCBzaGFkb3dpbmcgYXMgdGhlIGZ1bmN0aW9uIGlzIGV4ZWN1dGVkIGV4dGVybmFsbHkuXG4gICAgZm4oeyB2YXVsdFBhdGggfSk6IHZvaWQge1xuICAgICAgd2luZG93LmVsZWN0cm9uLmlwY1JlbmRlcmVyLnNlbmRTeW5jKCd2YXVsdC1vcGVuJywgdmF1bHRQYXRoLCBmYWxzZSk7XG4gICAgfSxcbiAgICBzaG91bGRTa2lwUHJlZmxpZ2h0Q2hlY2tzOiB0cnVlXG4gIH0pO1xuXG4gIC8vIFBvbGwgdW50aWwgdGhlIG5ldyB2YXVsdCdzIENMSSByZXNwb25kcyB3aXRoIHRoZSBjb3JyZWN0IGJhc2VQYXRoLlxuICBjb25zdCBkZWFkbGluZSA9IERhdGUubm93KCkgKyBQT0xMX1RJTUVPVVRfTVM7XG4gIHdoaWxlIChEYXRlLm5vdygpIDwgZGVhZGxpbmUpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgYmFzZVBhdGggPSBhd2FpdCBldmFsSW5PYnNpZGlhbih7XG4gICAgICAgIGZuKHsgYXBwIH0pOiBzdHJpbmcge1xuICAgICAgICAgIHJldHVybiAoYXBwLnZhdWx0LmFkYXB0ZXIgYXMgRmlsZVN5c3RlbUFkYXB0ZXIpLmdldEJhc2VQYXRoKCk7XG4gICAgICAgIH0sXG4gICAgICAgIHNob3VsZFNraXBQcmVmbGlnaHRDaGVja3M6IHRydWUsXG4gICAgICAgIHZhdWx0UGF0aFxuICAgICAgfSk7XG4gICAgICBpZiAoYmFzZVBhdGggPT09IHZhdWx0UGF0aCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfSBjYXRjaCB7XG4gICAgICAvLyBWYXVsdCBub3QgcmVhZHkgeWV0LlxuICAgIH1cbiAgICBhd2FpdCBuZXcgUHJvbWlzZSgocikgPT4ge1xuICAgICAgc2V0VGltZW91dChyLCBQT0xMX0lOVEVSVkFMX01TKTtcbiAgICB9KTtcbiAgfVxuICB0aHJvdyBuZXcgRXJyb3IoYFZhdWx0IGF0ICR7dmF1bHRQYXRofSBkaWQgbm90IGJlY29tZSByZWFkeSB3aXRoaW4gJHtTdHJpbmcoUE9MTF9USU1FT1VUX01TKX1tc2ApO1xufVxuXG4vKipcbiAqIFVucmVnaXN0ZXJzIGEgdmF1bHQgcGF0aCBmcm9tIHRoZSBydW5uaW5nIE9ic2lkaWFuIGluc3RhbmNlLlxuICpcbiAqIFNjaGVkdWxlcyB0aGUgdmF1bHQgd2luZG93IHRvIGNsb3NlLCB3YWl0cyBmb3IgaXQsIHRoZW4gcmVtb3Zlc1xuICogdGhlIHZhdWx0IGZyb20gdGhlIHJlZ2lzdHJ5IHZpYSBgdmF1bHQtcmVtb3ZlYCBJUEMuXG4gKlxuICogQHBhcmFtIHZhdWx0UGF0aCAtIFRoZSBhYnNvbHV0ZSBwYXRoIHRvIHRoZSB2YXVsdCBmb2xkZXIuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB1bnJlZ2lzdGVyVmF1bHQodmF1bHRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgLy8gU2NoZWR1bGUgdGhlIHZhdWx0IHdpbmRvdyB0byBjbG9zZSBmcm9tIHdpdGhpbiBpdHMgb3duIGNvbnRleHQuXG4gIC8vIFVzZSBzZXRUaW1lb3V0IHNvIHRoZSBDTEkgcmVzcG9uc2UgaXMgc2VudCBiZWZvcmUgdGhlIHdpbmRvdyBjbG9zZXMuXG4gIHRyeSB7XG4gICAgYXdhaXQgZXZhbEluT2JzaWRpYW4oe1xuICAgICAgZm4oKTogdm9pZCB7XG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICh3aW5kb3cuZWxlY3Ryb24gYXMgUGFydGlhbDxFbGVjdHJvbj4pLnJlbW90ZT8uZ2V0Q3VycmVudFdpbmRvdygpLmRlc3Ryb3koKTtcbiAgICAgICAgfSwgMCk7XG4gICAgICB9LFxuICAgICAgc2hvdWxkU2tpcFByZWZsaWdodENoZWNrczogdHJ1ZSxcbiAgICAgIHZhdWx0UGF0aFxuICAgIH0pO1xuICB9IGNhdGNoIHtcbiAgICAvLyBUaGUgd2luZG93IG1heSBoYXZlIGNsb3NlZCBiZWZvcmUgdGhlIHJlc3BvbnNlIHdhcyBzZW50IFx1MjAxNCB0aGF0J3MgT0suXG4gIH1cblxuICAvLyBXYWl0IGZvciB0aGUgd2luZG93IHRvIGFjdHVhbGx5IGNsb3NlLlxuICBhd2FpdCBuZXcgUHJvbWlzZSgocikgPT4ge1xuICAgIHNldFRpbWVvdXQociwgQ0xPU0VfREVMQVlfTVMpO1xuICB9KTtcblxuICAvLyBSZW1vdmUgZnJvbSB0aGUgcmVnaXN0cnkgKGZyb20gYW55IHJlbWFpbmluZyB2YXVsdCdzIGNvbnRleHQpLlxuICBhd2FpdCBldmFsSW5PYnNpZGlhbih7XG4gICAgYXJnczogeyB2YXVsdFBhdGggfSxcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tc2hhZG93IC0tIE5vIGFjdHVhbCBzaGFkb3dpbmcgYXMgdGhlIGZ1bmN0aW9uIGlzIGV4ZWN1dGVkIGV4dGVybmFsbHkuXG4gICAgZm4oeyB2YXVsdFBhdGggfSk6IHZvaWQge1xuICAgICAgd2luZG93LmVsZWN0cm9uLmlwY1JlbmRlcmVyLnNlbmRTeW5jKCd2YXVsdC1yZW1vdmUnLCB2YXVsdFBhdGgpO1xuICAgIH0sXG4gICAgc2hvdWxkU2tpcFByZWZsaWdodENoZWNrczogdHJ1ZVxuICB9KTtcbn1cblxuLyogdjggaWdub3JlIHN0b3AgKi9cbiJdLAogICJtYXBwaW5ncyI6ICJBQVVBLFNBQVMsc0JBQXNCO0FBRS9CLE1BQU0sbUJBQW1CO0FBQ3pCLE1BQU0sa0JBQWtCO0FBQ3hCLE1BQU0saUJBQWlCO0FBc0J2QixlQUFzQixjQUFjLFdBQWtDO0FBSXBFLFFBQU0sZUFBZTtBQUFBLElBQ25CLE1BQU0sRUFBRSxVQUFVO0FBQUE7QUFBQSxJQUVsQixHQUFHLEVBQUUsV0FBQUEsV0FBVSxHQUFTO0FBQ3RCLGFBQU8sU0FBUyxZQUFZLFNBQVMsY0FBY0EsWUFBVyxLQUFLO0FBQUEsSUFDckU7QUFBQSxJQUNBLDJCQUEyQjtBQUFBLEVBQzdCLENBQUM7QUFHRCxRQUFNLFdBQVcsS0FBSyxJQUFJLElBQUk7QUFDOUIsU0FBTyxLQUFLLElBQUksSUFBSSxVQUFVO0FBQzVCLFFBQUk7QUFDRixZQUFNLFdBQVcsTUFBTSxlQUFlO0FBQUEsUUFDcEMsR0FBRyxFQUFFLElBQUksR0FBVztBQUNsQixpQkFBUSxJQUFJLE1BQU0sUUFBOEIsWUFBWTtBQUFBLFFBQzlEO0FBQUEsUUFDQSwyQkFBMkI7QUFBQSxRQUMzQjtBQUFBLE1BQ0YsQ0FBQztBQUNELFVBQUksYUFBYSxXQUFXO0FBQzFCO0FBQUEsTUFDRjtBQUFBLElBQ0YsUUFBUTtBQUFBLElBRVI7QUFDQSxVQUFNLElBQUksUUFBUSxDQUFDLE1BQU07QUFDdkIsaUJBQVcsR0FBRyxnQkFBZ0I7QUFBQSxJQUNoQyxDQUFDO0FBQUEsRUFDSDtBQUNBLFFBQU0sSUFBSSxNQUFNLFlBQVksU0FBUyxnQ0FBZ0MsT0FBTyxlQUFlLENBQUMsSUFBSTtBQUNsRztBQVVBLGVBQXNCLGdCQUFnQixXQUFrQztBQUd0RSxNQUFJO0FBQ0YsVUFBTSxlQUFlO0FBQUEsTUFDbkIsS0FBVztBQUNULG1CQUFXLE1BQU07QUFDZixVQUFDLE9BQU8sU0FBK0IsUUFBUSxpQkFBaUIsRUFBRSxRQUFRO0FBQUEsUUFDNUUsR0FBRyxDQUFDO0FBQUEsTUFDTjtBQUFBLE1BQ0EsMkJBQTJCO0FBQUEsTUFDM0I7QUFBQSxJQUNGLENBQUM7QUFBQSxFQUNILFFBQVE7QUFBQSxFQUVSO0FBR0EsUUFBTSxJQUFJLFFBQVEsQ0FBQyxNQUFNO0FBQ3ZCLGVBQVcsR0FBRyxjQUFjO0FBQUEsRUFDOUIsQ0FBQztBQUdELFFBQU0sZUFBZTtBQUFBLElBQ25CLE1BQU0sRUFBRSxVQUFVO0FBQUE7QUFBQSxJQUVsQixHQUFHLEVBQUUsV0FBQUEsV0FBVSxHQUFTO0FBQ3RCLGFBQU8sU0FBUyxZQUFZLFNBQVMsZ0JBQWdCQSxVQUFTO0FBQUEsSUFDaEU7QUFBQSxJQUNBLDJCQUEyQjtBQUFBLEVBQzdCLENBQUM7QUFDSDsiLAogICJuYW1lcyI6IFsidmF1bHRQYXRoIl0KfQo=
|
|
Binary file
|