obsidian-integration-testing 4.4.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +51 -54
  2. package/dist/lib/cjs/global-setup-core.cjs +13 -9
  3. package/dist/lib/cjs/global-setup-core.d.cts +1 -1
  4. package/dist/lib/cjs/index.cjs +1 -4
  5. package/dist/lib/cjs/index.d.cts +2 -3
  6. package/dist/lib/cjs/kill-process-tree.cjs +57 -0
  7. package/dist/lib/cjs/kill-process-tree.d.cts +16 -0
  8. package/dist/lib/cjs/library.cjs +1 -1
  9. package/dist/lib/cjs/obsidian-config.cjs +11 -85
  10. package/dist/lib/cjs/obsidian-config.d.cts +12 -72
  11. package/dist/lib/cjs/obsidian-installer.cjs +180 -0
  12. package/dist/lib/cjs/obsidian-installer.d.cts +45 -0
  13. package/dist/lib/cjs/obsidian-instance.cjs +100 -0
  14. package/dist/lib/cjs/obsidian-instance.d.cts +55 -0
  15. package/dist/lib/cjs/obsidian-version-switch.cjs +105 -0
  16. package/dist/lib/cjs/obsidian-version-switch.d.cts +63 -0
  17. package/dist/lib/cjs/obsidian-version.cjs +85 -0
  18. package/dist/lib/cjs/obsidian-version.d.cts +111 -0
  19. package/dist/lib/cjs/transport-desktop-cdp.cjs +121 -7
  20. package/dist/lib/cjs/transport-desktop-cdp.d.cts +75 -14
  21. package/dist/lib/cjs/transport-factory.cjs +63 -32
  22. package/dist/lib/cjs/transport-options.cjs +1 -1
  23. package/dist/lib/cjs/transport-options.d.cts +37 -14
  24. package/dist/lib/cjs/transport.cjs +1 -1
  25. package/dist/lib/cjs/transport.d.cts +1 -1
  26. package/dist/lib/cjs/vitest/global-setup.cjs +2 -2
  27. package/dist/lib/cjs/vitest/typings.d.cts +1 -1
  28. package/dist/lib/esm/global-setup-core.d.mts +1 -1
  29. package/dist/lib/esm/global-setup-core.mjs +13 -9
  30. package/dist/lib/esm/index.d.mts +2 -3
  31. package/dist/lib/esm/index.mjs +1 -3
  32. package/dist/lib/esm/kill-process-tree.d.mts +16 -0
  33. package/dist/lib/esm/kill-process-tree.mjs +23 -0
  34. package/dist/lib/esm/library.mjs +1 -1
  35. package/dist/lib/esm/obsidian-config.d.mts +12 -72
  36. package/dist/lib/esm/obsidian-config.mjs +10 -78
  37. package/dist/lib/esm/obsidian-installer.d.mts +45 -0
  38. package/dist/lib/esm/obsidian-installer.mjs +158 -0
  39. package/dist/lib/esm/obsidian-instance.d.mts +55 -0
  40. package/dist/lib/esm/obsidian-instance.mjs +75 -0
  41. package/dist/lib/esm/obsidian-version-switch.d.mts +63 -0
  42. package/dist/lib/esm/obsidian-version-switch.mjs +89 -0
  43. package/dist/lib/esm/obsidian-version.d.mts +111 -0
  44. package/dist/lib/esm/obsidian-version.mjs +55 -0
  45. package/dist/lib/esm/transport-desktop-cdp.d.mts +75 -14
  46. package/dist/lib/esm/transport-desktop-cdp.mjs +125 -7
  47. package/dist/lib/esm/transport-factory.mjs +68 -28
  48. package/dist/lib/esm/transport-options.d.mts +37 -14
  49. package/dist/lib/esm/transport.d.mts +1 -1
  50. package/dist/lib/esm/vitest/global-setup.mjs +2 -2
  51. package/dist/lib/esm/vitest/typings.d.mts +1 -1
  52. package/dist/obsidian-integration-testing-5.0.0.tgz +0 -0
  53. package/package.json +16 -15
  54. package/dist/lib/cjs/transport-desktop-cli.cjs +0 -540
  55. package/dist/lib/cjs/transport-desktop-cli.d.cts +0 -154
  56. package/dist/lib/esm/transport-desktop-cli.d.mts +0 -154
  57. package/dist/lib/esm/transport-desktop-cli.mjs +0 -520
  58. package/dist/obsidian-integration-testing-4.4.0.tgz +0 -0
@@ -0,0 +1,111 @@
1
+ /**
2
+ * @file
3
+ *
4
+ * Pure helpers for resolving Obsidian desktop version specifiers.
5
+ *
6
+ * A version specifier is either an explicit `x.y.z` string or one of the
7
+ * channel aliases {@link PUBLIC_LATEST} / {@link CATALYST_LATEST}, which resolve
8
+ * against Obsidian's published desktop releases manifest.
9
+ *
10
+ * The network call that fetches the manifest lives in the integration-time
11
+ * version-switch module; everything here is pure and unit-tested.
12
+ */
13
+ /**
14
+ * Version specifier alias resolving to the latest **public** desktop release
15
+ * (the manifest's `latestVersion`).
16
+ */
17
+ export declare const PUBLIC_LATEST = "public-latest";
18
+ /**
19
+ * Version specifier alias resolving to the latest **catalyst** (early access /
20
+ * insider) desktop release (the manifest's `beta.latestVersion`).
21
+ */
22
+ export declare const CATALYST_LATEST = "catalyst-latest";
23
+ /**
24
+ * URL of Obsidian's desktop releases manifest (raw JSON).
25
+ */
26
+ export declare const DESKTOP_RELEASES_MANIFEST_URL = "https://raw.githubusercontent.com/obsidianmd/obsidian-releases/master/desktop-releases.json";
27
+ /**
28
+ * A version specifier resolved against a release channel.
29
+ */
30
+ export interface ChannelVersionSpec {
31
+ /** The channel to resolve against the manifest. */
32
+ readonly channel: ReleaseChannel;
33
+ /** Discriminant. */
34
+ readonly kind: 'channel';
35
+ }
36
+ /**
37
+ * The `beta` (catalyst) entry of {@link DesktopReleasesManifest}.
38
+ */
39
+ export interface DesktopReleasesBeta {
40
+ /** The latest catalyst version, e.g. `'1.13.1'`. */
41
+ readonly latestVersion: string;
42
+ }
43
+ /**
44
+ * The subset of Obsidian's `desktop-releases.json` this library reads.
45
+ */
46
+ export interface DesktopReleasesManifest {
47
+ /**
48
+ * The latest catalyst (early access / insider) release, when present.
49
+ */
50
+ readonly beta?: DesktopReleasesBeta;
51
+ /**
52
+ * The latest public (stable) version, e.g. `'1.12.7'`.
53
+ */
54
+ readonly latestVersion: string;
55
+ }
56
+ /**
57
+ * A version specifier naming a concrete `x.y.z` version.
58
+ */
59
+ export interface ExplicitVersionSpec {
60
+ /** Discriminant. */
61
+ readonly kind: 'explicit';
62
+ /** The concrete `x.y.z` version. */
63
+ readonly version: string;
64
+ }
65
+ /**
66
+ * A release channel resolved from a channel-alias specifier.
67
+ *
68
+ * - `public` — the latest stable release.
69
+ * - `catalyst` — the latest early access / insider release.
70
+ */
71
+ export type ReleaseChannel = 'catalyst' | 'public';
72
+ /**
73
+ * The parsed form of a version specifier.
74
+ *
75
+ * - `explicit` — a concrete `x.y.z` version.
76
+ * - `channel` — a channel alias to be resolved against the manifest.
77
+ */
78
+ export type VersionSpec = ChannelVersionSpec | ExplicitVersionSpec;
79
+ /**
80
+ * Compares two `x.y.z` version strings numerically, segment by segment.
81
+ *
82
+ * @param a - The first version.
83
+ * @param b - The second version.
84
+ * @returns A negative number if `a < b`, `0` if equal, a positive number if `a > b`.
85
+ */
86
+ export declare function compareVersions(a: string, b: string): number;
87
+ /**
88
+ * Returns the user-data asar file name for a given version, matching the name
89
+ * Obsidian itself uses when it downloads an update (`obsidian-<version>.asar`).
90
+ *
91
+ * @param version - A concrete `x.y.z` version.
92
+ * @returns The asar file name.
93
+ */
94
+ export declare function getVersionAsarFileName(version: string): string;
95
+ /**
96
+ * Parses a version specifier into either an explicit version or a channel alias.
97
+ *
98
+ * @param spec - The specifier: an `x.y.z` string, {@link PUBLIC_LATEST}, or {@link CATALYST_LATEST}.
99
+ * @returns The parsed {@link VersionSpec}.
100
+ * @throws Error if the specifier is neither a valid `x.y.z` version nor a known alias.
101
+ */
102
+ export declare function parseVersionSpec(spec: string): VersionSpec;
103
+ /**
104
+ * Resolves a channel to a concrete version using a desktop releases manifest.
105
+ *
106
+ * @param manifest - The parsed manifest.
107
+ * @param channel - The channel to resolve.
108
+ * @returns The concrete `x.y.z` version for the channel.
109
+ * @throws Error if the catalyst channel is requested but the manifest has no `beta` entry.
110
+ */
111
+ export declare function resolveVersionFromManifest(manifest: DesktopReleasesManifest, channel: ReleaseChannel): string;
@@ -0,0 +1,55 @@
1
+ const PUBLIC_LATEST = "public-latest";
2
+ const CATALYST_LATEST = "catalyst-latest";
3
+ const DESKTOP_RELEASES_MANIFEST_URL = "https://raw.githubusercontent.com/obsidianmd/obsidian-releases/master/desktop-releases.json";
4
+ const EXPLICIT_VERSION_PATTERN = /^\d+\.\d+\.\d+$/;
5
+ const VERSION_SEGMENT_COUNT = 3;
6
+ function compareVersions(a, b) {
7
+ const aSegments = parseVersionSegments(a);
8
+ const bSegments = parseVersionSegments(b);
9
+ for (let i = 0; i < VERSION_SEGMENT_COUNT; i++) {
10
+ const diff = (aSegments[i] ?? 0) - (bSegments[i] ?? 0);
11
+ if (diff !== 0) {
12
+ return diff;
13
+ }
14
+ }
15
+ return 0;
16
+ }
17
+ function getVersionAsarFileName(version) {
18
+ return `obsidian-${version}.asar`;
19
+ }
20
+ function parseVersionSpec(spec) {
21
+ if (spec === PUBLIC_LATEST) {
22
+ return { channel: "public", kind: "channel" };
23
+ }
24
+ if (spec === CATALYST_LATEST) {
25
+ return { channel: "catalyst", kind: "channel" };
26
+ }
27
+ if (EXPLICIT_VERSION_PATTERN.test(spec)) {
28
+ return { kind: "explicit", version: spec };
29
+ }
30
+ throw new Error(
31
+ `Invalid Obsidian version "${spec}". Expected an "x.y.z" version, "${PUBLIC_LATEST}", or "${CATALYST_LATEST}".`
32
+ );
33
+ }
34
+ function resolveVersionFromManifest(manifest, channel) {
35
+ if (channel === "public") {
36
+ return manifest.latestVersion;
37
+ }
38
+ if (!manifest.beta) {
39
+ throw new Error("Desktop releases manifest has no catalyst (beta) release.");
40
+ }
41
+ return manifest.beta.latestVersion;
42
+ }
43
+ function parseVersionSegments(version) {
44
+ return version.split(".").map((segment) => Number.parseInt(segment, 10));
45
+ }
46
+ export {
47
+ CATALYST_LATEST,
48
+ DESKTOP_RELEASES_MANIFEST_URL,
49
+ PUBLIC_LATEST,
50
+ compareVersions,
51
+ getVersionAsarFileName,
52
+ parseVersionSpec,
53
+ resolveVersionFromManifest
54
+ };
55
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL29ic2lkaWFuLXZlcnNpb24udHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qKlxuICogQGZpbGVcbiAqXG4gKiBQdXJlIGhlbHBlcnMgZm9yIHJlc29sdmluZyBPYnNpZGlhbiBkZXNrdG9wIHZlcnNpb24gc3BlY2lmaWVycy5cbiAqXG4gKiBBIHZlcnNpb24gc3BlY2lmaWVyIGlzIGVpdGhlciBhbiBleHBsaWNpdCBgeC55LnpgIHN0cmluZyBvciBvbmUgb2YgdGhlXG4gKiBjaGFubmVsIGFsaWFzZXMge0BsaW5rIFBVQkxJQ19MQVRFU1R9IC8ge0BsaW5rIENBVEFMWVNUX0xBVEVTVH0sIHdoaWNoIHJlc29sdmVcbiAqIGFnYWluc3QgT2JzaWRpYW4ncyBwdWJsaXNoZWQgZGVza3RvcCByZWxlYXNlcyBtYW5pZmVzdC5cbiAqXG4gKiBUaGUgbmV0d29yayBjYWxsIHRoYXQgZmV0Y2hlcyB0aGUgbWFuaWZlc3QgbGl2ZXMgaW4gdGhlIGludGVncmF0aW9uLXRpbWVcbiAqIHZlcnNpb24tc3dpdGNoIG1vZHVsZTsgZXZlcnl0aGluZyBoZXJlIGlzIHB1cmUgYW5kIHVuaXQtdGVzdGVkLlxuICovXG5cbi8qKlxuICogVmVyc2lvbiBzcGVjaWZpZXIgYWxpYXMgcmVzb2x2aW5nIHRvIHRoZSBsYXRlc3QgKipwdWJsaWMqKiBkZXNrdG9wIHJlbGVhc2VcbiAqICh0aGUgbWFuaWZlc3QncyBgbGF0ZXN0VmVyc2lvbmApLlxuICovXG5leHBvcnQgY29uc3QgUFVCTElDX0xBVEVTVCA9ICdwdWJsaWMtbGF0ZXN0JztcblxuLyoqXG4gKiBWZXJzaW9uIHNwZWNpZmllciBhbGlhcyByZXNvbHZpbmcgdG8gdGhlIGxhdGVzdCAqKmNhdGFseXN0KiogKGVhcmx5IGFjY2VzcyAvXG4gKiBpbnNpZGVyKSBkZXNrdG9wIHJlbGVhc2UgKHRoZSBtYW5pZmVzdCdzIGBiZXRhLmxhdGVzdFZlcnNpb25gKS5cbiAqL1xuZXhwb3J0IGNvbnN0IENBVEFMWVNUX0xBVEVTVCA9ICdjYXRhbHlzdC1sYXRlc3QnO1xuXG4vKipcbiAqIFVSTCBvZiBPYnNpZGlhbidzIGRlc2t0b3AgcmVsZWFzZXMgbWFuaWZlc3QgKHJhdyBKU09OKS5cbiAqL1xuZXhwb3J0IGNvbnN0IERFU0tUT1BfUkVMRUFTRVNfTUFOSUZFU1RfVVJMID0gJ2h0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9vYnNpZGlhbm1kL29ic2lkaWFuLXJlbGVhc2VzL21hc3Rlci9kZXNrdG9wLXJlbGVhc2VzLmpzb24nO1xuXG5jb25zdCBFWFBMSUNJVF9WRVJTSU9OX1BBVFRFUk4gPSAvXlxcZCtcXC5cXGQrXFwuXFxkKyQvO1xuY29uc3QgVkVSU0lPTl9TRUdNRU5UX0NPVU5UID0gMztcblxuLyoqXG4gKiBBIHZlcnNpb24gc3BlY2lmaWVyIHJlc29sdmVkIGFnYWluc3QgYSByZWxlYXNlIGNoYW5uZWwuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ2hhbm5lbFZlcnNpb25TcGVjIHtcbiAgLyoqIFRoZSBjaGFubmVsIHRvIHJlc29sdmUgYWdhaW5zdCB0aGUgbWFuaWZlc3QuICovXG4gIHJlYWRvbmx5IGNoYW5uZWw6IFJlbGVhc2VDaGFubmVsO1xuXG4gIC8qKiBEaXNjcmltaW5hbnQuICovXG4gIHJlYWRvbmx5IGtpbmQ6ICdjaGFubmVsJztcbn1cblxuLyoqXG4gKiBUaGUgYGJldGFgIChjYXRhbHlzdCkgZW50cnkgb2Yge0BsaW5rIERlc2t0b3BSZWxlYXNlc01hbmlmZXN0fS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZXNrdG9wUmVsZWFzZXNCZXRhIHtcbiAgLyoqIFRoZSBsYXRlc3QgY2F0YWx5c3QgdmVyc2lvbiwgZS5nLiBgJzEuMTMuMSdgLiAqL1xuICByZWFkb25seSBsYXRlc3RWZXJzaW9uOiBzdHJpbmc7XG59XG5cbi8qKlxuICogVGhlIHN1YnNldCBvZiBPYnNpZGlhbidzIGBkZXNrdG9wLXJlbGVhc2VzLmpzb25gIHRoaXMgbGlicmFyeSByZWFkcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZXNrdG9wUmVsZWFzZXNNYW5pZmVzdCB7XG4gIC8qKlxuICAgKiBUaGUgbGF0ZXN0IGNhdGFseXN0IChlYXJseSBhY2Nlc3MgLyBpbnNpZGVyKSByZWxlYXNlLCB3aGVuIHByZXNlbnQuXG4gICAqL1xuICByZWFkb25seSBiZXRhPzogRGVza3RvcFJlbGVhc2VzQmV0YTtcblxuICAvKipcbiAgICogVGhlIGxhdGVzdCBwdWJsaWMgKHN0YWJsZSkgdmVyc2lvbiwgZS5nLiBgJzEuMTIuNydgLlxuICAgKi9cbiAgcmVhZG9ubHkgbGF0ZXN0VmVyc2lvbjogc3RyaW5nO1xufVxuXG4vKipcbiAqIEEgdmVyc2lvbiBzcGVjaWZpZXIgbmFtaW5nIGEgY29uY3JldGUgYHgueS56YCB2ZXJzaW9uLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEV4cGxpY2l0VmVyc2lvblNwZWMge1xuICAvKiogRGlzY3JpbWluYW50LiAqL1xuICByZWFkb25seSBraW5kOiAnZXhwbGljaXQnO1xuXG4gIC8qKiBUaGUgY29uY3JldGUgYHgueS56YCB2ZXJzaW9uLiAqL1xuICByZWFkb25seSB2ZXJzaW9uOiBzdHJpbmc7XG59XG5cbi8qKlxuICogQSByZWxlYXNlIGNoYW5uZWwgcmVzb2x2ZWQgZnJvbSBhIGNoYW5uZWwtYWxpYXMgc3BlY2lmaWVyLlxuICpcbiAqIC0gYHB1YmxpY2AgXHUyMDE0IHRoZSBsYXRlc3Qgc3RhYmxlIHJlbGVhc2UuXG4gKiAtIGBjYXRhbHlzdGAgXHUyMDE0IHRoZSBsYXRlc3QgZWFybHkgYWNjZXNzIC8gaW5zaWRlciByZWxlYXNlLlxuICovXG5leHBvcnQgdHlwZSBSZWxlYXNlQ2hhbm5lbCA9ICdjYXRhbHlzdCcgfCAncHVibGljJztcblxuLyoqXG4gKiBUaGUgcGFyc2VkIGZvcm0gb2YgYSB2ZXJzaW9uIHNwZWNpZmllci5cbiAqXG4gKiAtIGBleHBsaWNpdGAgXHUyMDE0IGEgY29uY3JldGUgYHgueS56YCB2ZXJzaW9uLlxuICogLSBgY2hhbm5lbGAgXHUyMDE0IGEgY2hhbm5lbCBhbGlhcyB0byBiZSByZXNvbHZlZCBhZ2FpbnN0IHRoZSBtYW5pZmVzdC5cbiAqL1xuZXhwb3J0IHR5cGUgVmVyc2lvblNwZWMgPSBDaGFubmVsVmVyc2lvblNwZWMgfCBFeHBsaWNpdFZlcnNpb25TcGVjO1xuXG4vKipcbiAqIENvbXBhcmVzIHR3byBgeC55LnpgIHZlcnNpb24gc3RyaW5ncyBudW1lcmljYWxseSwgc2VnbWVudCBieSBzZWdtZW50LlxuICpcbiAqIEBwYXJhbSBhIC0gVGhlIGZpcnN0IHZlcnNpb24uXG4gKiBAcGFyYW0gYiAtIFRoZSBzZWNvbmQgdmVyc2lvbi5cbiAqIEByZXR1cm5zIEEgbmVnYXRpdmUgbnVtYmVyIGlmIGBhIDwgYmAsIGAwYCBpZiBlcXVhbCwgYSBwb3NpdGl2ZSBudW1iZXIgaWYgYGEgPiBiYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbXBhcmVWZXJzaW9ucyhhOiBzdHJpbmcsIGI6IHN0cmluZyk6IG51bWJlciB7XG4gIGNvbnN0IGFTZWdtZW50cyA9IHBhcnNlVmVyc2lvblNlZ21lbnRzKGEpO1xuICBjb25zdCBiU2VnbWVudHMgPSBwYXJzZVZlcnNpb25TZWdtZW50cyhiKTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IFZFUlNJT05fU0VHTUVOVF9DT1VOVDsgaSsrKSB7XG4gICAgY29uc3QgZGlmZiA9IChhU2VnbWVudHNbaV0gPz8gMCkgLSAoYlNlZ21lbnRzW2ldID8/IDApO1xuICAgIGlmIChkaWZmICE9PSAwKSB7XG4gICAgICByZXR1cm4gZGlmZjtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gMDtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSB1c2VyLWRhdGEgYXNhciBmaWxlIG5hbWUgZm9yIGEgZ2l2ZW4gdmVyc2lvbiwgbWF0Y2hpbmcgdGhlIG5hbWVcbiAqIE9ic2lkaWFuIGl0c2VsZiB1c2VzIHdoZW4gaXQgZG93bmxvYWRzIGFuIHVwZGF0ZSAoYG9ic2lkaWFuLTx2ZXJzaW9uPi5hc2FyYCkuXG4gKlxuICogQHBhcmFtIHZlcnNpb24gLSBBIGNvbmNyZXRlIGB4LnkuemAgdmVyc2lvbi5cbiAqIEByZXR1cm5zIFRoZSBhc2FyIGZpbGUgbmFtZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFZlcnNpb25Bc2FyRmlsZU5hbWUodmVyc2lvbjogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGBvYnNpZGlhbi0ke3ZlcnNpb259LmFzYXJgO1xufVxuXG4vKipcbiAqIFBhcnNlcyBhIHZlcnNpb24gc3BlY2lmaWVyIGludG8gZWl0aGVyIGFuIGV4cGxpY2l0IHZlcnNpb24gb3IgYSBjaGFubmVsIGFsaWFzLlxuICpcbiAqIEBwYXJhbSBzcGVjIC0gVGhlIHNwZWNpZmllcjogYW4gYHgueS56YCBzdHJpbmcsIHtAbGluayBQVUJMSUNfTEFURVNUfSwgb3Ige0BsaW5rIENBVEFMWVNUX0xBVEVTVH0uXG4gKiBAcmV0dXJucyBUaGUgcGFyc2VkIHtAbGluayBWZXJzaW9uU3BlY30uXG4gKiBAdGhyb3dzIEVycm9yIGlmIHRoZSBzcGVjaWZpZXIgaXMgbmVpdGhlciBhIHZhbGlkIGB4LnkuemAgdmVyc2lvbiBub3IgYSBrbm93biBhbGlhcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlVmVyc2lvblNwZWMoc3BlYzogc3RyaW5nKTogVmVyc2lvblNwZWMge1xuICBpZiAoc3BlYyA9PT0gUFVCTElDX0xBVEVTVCkge1xuICAgIHJldHVybiB7IGNoYW5uZWw6ICdwdWJsaWMnLCBraW5kOiAnY2hhbm5lbCcgfTtcbiAgfVxuXG4gIGlmIChzcGVjID09PSBDQVRBTFlTVF9MQVRFU1QpIHtcbiAgICByZXR1cm4geyBjaGFubmVsOiAnY2F0YWx5c3QnLCBraW5kOiAnY2hhbm5lbCcgfTtcbiAgfVxuXG4gIGlmIChFWFBMSUNJVF9WRVJTSU9OX1BBVFRFUk4udGVzdChzcGVjKSkge1xuICAgIHJldHVybiB7IGtpbmQ6ICdleHBsaWNpdCcsIHZlcnNpb246IHNwZWMgfTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihcbiAgICBgSW52YWxpZCBPYnNpZGlhbiB2ZXJzaW9uIFwiJHtzcGVjfVwiLiBFeHBlY3RlZCBhbiBcIngueS56XCIgdmVyc2lvbiwgXCIke1BVQkxJQ19MQVRFU1R9XCIsIG9yIFwiJHtDQVRBTFlTVF9MQVRFU1R9XCIuYFxuICApO1xufVxuXG4vKipcbiAqIFJlc29sdmVzIGEgY2hhbm5lbCB0byBhIGNvbmNyZXRlIHZlcnNpb24gdXNpbmcgYSBkZXNrdG9wIHJlbGVhc2VzIG1hbmlmZXN0LlxuICpcbiAqIEBwYXJhbSBtYW5pZmVzdCAtIFRoZSBwYXJzZWQgbWFuaWZlc3QuXG4gKiBAcGFyYW0gY2hhbm5lbCAtIFRoZSBjaGFubmVsIHRvIHJlc29sdmUuXG4gKiBAcmV0dXJucyBUaGUgY29uY3JldGUgYHgueS56YCB2ZXJzaW9uIGZvciB0aGUgY2hhbm5lbC5cbiAqIEB0aHJvd3MgRXJyb3IgaWYgdGhlIGNhdGFseXN0IGNoYW5uZWwgaXMgcmVxdWVzdGVkIGJ1dCB0aGUgbWFuaWZlc3QgaGFzIG5vIGBiZXRhYCBlbnRyeS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVWZXJzaW9uRnJvbU1hbmlmZXN0KG1hbmlmZXN0OiBEZXNrdG9wUmVsZWFzZXNNYW5pZmVzdCwgY2hhbm5lbDogUmVsZWFzZUNoYW5uZWwpOiBzdHJpbmcge1xuICBpZiAoY2hhbm5lbCA9PT0gJ3B1YmxpYycpIHtcbiAgICByZXR1cm4gbWFuaWZlc3QubGF0ZXN0VmVyc2lvbjtcbiAgfVxuXG4gIGlmICghbWFuaWZlc3QuYmV0YSkge1xuICAgIHRocm93IG5ldyBFcnJvcignRGVza3RvcCByZWxlYXNlcyBtYW5pZmVzdCBoYXMgbm8gY2F0YWx5c3QgKGJldGEpIHJlbGVhc2UuJyk7XG4gIH1cblxuICByZXR1cm4gbWFuaWZlc3QuYmV0YS5sYXRlc3RWZXJzaW9uO1xufVxuXG4vKipcbiAqIFNwbGl0cyBhbiBgeC55LnpgIHZlcnNpb24gaW50byBpdHMgbnVtZXJpYyBzZWdtZW50cy5cbiAqXG4gKiBAcGFyYW0gdmVyc2lvbiAtIFRoZSB2ZXJzaW9uIHN0cmluZy5cbiAqIEByZXR1cm5zIFRoZSBudW1lcmljIHNlZ21lbnRzLlxuICovXG5mdW5jdGlvbiBwYXJzZVZlcnNpb25TZWdtZW50cyh2ZXJzaW9uOiBzdHJpbmcpOiBudW1iZXJbXSB7XG4gIHJldHVybiB2ZXJzaW9uLnNwbGl0KCcuJykubWFwKChzZWdtZW50KSA9PiBOdW1iZXIucGFyc2VJbnQoc2VnbWVudCwgMTApKTtcbn1cbiJdLAogICJtYXBwaW5ncyI6ICJBQWlCTyxNQUFNLGdCQUFnQjtBQU10QixNQUFNLGtCQUFrQjtBQUt4QixNQUFNLGdDQUFnQztBQUU3QyxNQUFNLDJCQUEyQjtBQUNqQyxNQUFNLHdCQUF3QjtBQXNFdkIsU0FBUyxnQkFBZ0IsR0FBVyxHQUFtQjtBQUM1RCxRQUFNLFlBQVkscUJBQXFCLENBQUM7QUFDeEMsUUFBTSxZQUFZLHFCQUFxQixDQUFDO0FBRXhDLFdBQVMsSUFBSSxHQUFHLElBQUksdUJBQXVCLEtBQUs7QUFDOUMsVUFBTSxRQUFRLFVBQVUsQ0FBQyxLQUFLLE1BQU0sVUFBVSxDQUFDLEtBQUs7QUFDcEQsUUFBSSxTQUFTLEdBQUc7QUFDZCxhQUFPO0FBQUEsSUFDVDtBQUFBLEVBQ0Y7QUFFQSxTQUFPO0FBQ1Q7QUFTTyxTQUFTLHVCQUF1QixTQUF5QjtBQUM5RCxTQUFPLFlBQVksT0FBTztBQUM1QjtBQVNPLFNBQVMsaUJBQWlCLE1BQTJCO0FBQzFELE1BQUksU0FBUyxlQUFlO0FBQzFCLFdBQU8sRUFBRSxTQUFTLFVBQVUsTUFBTSxVQUFVO0FBQUEsRUFDOUM7QUFFQSxNQUFJLFNBQVMsaUJBQWlCO0FBQzVCLFdBQU8sRUFBRSxTQUFTLFlBQVksTUFBTSxVQUFVO0FBQUEsRUFDaEQ7QUFFQSxNQUFJLHlCQUF5QixLQUFLLElBQUksR0FBRztBQUN2QyxXQUFPLEVBQUUsTUFBTSxZQUFZLFNBQVMsS0FBSztBQUFBLEVBQzNDO0FBRUEsUUFBTSxJQUFJO0FBQUEsSUFDUiw2QkFBNkIsSUFBSSxvQ0FBb0MsYUFBYSxVQUFVLGVBQWU7QUFBQSxFQUM3RztBQUNGO0FBVU8sU0FBUywyQkFBMkIsVUFBbUMsU0FBaUM7QUFDN0csTUFBSSxZQUFZLFVBQVU7QUFDeEIsV0FBTyxTQUFTO0FBQUEsRUFDbEI7QUFFQSxNQUFJLENBQUMsU0FBUyxNQUFNO0FBQ2xCLFVBQU0sSUFBSSxNQUFNLDJEQUEyRDtBQUFBLEVBQzdFO0FBRUEsU0FBTyxTQUFTLEtBQUs7QUFDdkI7QUFRQSxTQUFTLHFCQUFxQixTQUEyQjtBQUN2RCxTQUFPLFFBQVEsTUFBTSxHQUFHLEVBQUUsSUFBSSxDQUFDLFlBQVksT0FBTyxTQUFTLFNBQVMsRUFBRSxDQUFDO0FBQ3pFOyIsCiAgIm5hbWVzIjogW10KfQo=
@@ -4,18 +4,17 @@
4
4
  * Desktop CDP transport — evaluates expressions via Chrome DevTools Protocol
5
5
  * over WebSocket and manages vaults via Electron IPC.
6
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.
7
+ * Two modes:
8
+ * - **Owned (default)**: the transport launches and owns an isolated Obsidian
9
+ * instance against a temporary `--user-data-dir` on a free `--remote-debugging-port`,
10
+ * never touching the user's Obsidian. Supports version pinning via the user-data asar.
11
+ * - **Attach**: when an explicit CDP port is configured, the transport connects
12
+ * to an already-running Obsidian on that port.
10
13
  *
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)
14
+ * It connects to page targets, sends `Runtime.evaluate` commands, and routes to
15
+ * the correct vault target using `getBasePath()` probing.
15
16
  *
16
- * Requirements:
17
- * - Obsidian must be running with remote debugging enabled (port 8315)
18
- * - Node.js 22+ (uses built-in `WebSocket` and `fetch` globals)
17
+ * Requirements: Node.js 22+ (uses built-in `WebSocket` and `fetch` globals).
19
18
  */
20
19
  import type { ObsidianTransport, TransportEvalOptions } from './transport.mjs';
21
20
  /**
@@ -27,7 +26,9 @@ export interface DesktopCdpTransportConfig {
27
26
  */
28
27
  cdpHost?: string;
29
28
  /**
30
- * CDP port. Defaults to `8315`.
29
+ * CDP port for **attach** mode (the `--remote-debugging-port` the running
30
+ * Obsidian was launched with). In owned-instance mode this is ignored — a
31
+ * free port is chosen at launch.
31
32
  */
32
33
  cdpPort?: number;
33
34
  /**
@@ -35,6 +36,37 @@ export interface DesktopCdpTransportConfig {
35
36
  * Defaults to `30000`.
36
37
  */
37
38
  commandTimeoutInMilliseconds?: number;
39
+ /**
40
+ * When set, the transport launches and owns an isolated Obsidian instance
41
+ * instead of attaching to a running one. This is the default desktop mode.
42
+ */
43
+ ownedInstance?: OwnedInstanceConfig;
44
+ }
45
+ /**
46
+ * An asar to provision into a harness-owned instance's user-data dir before launch.
47
+ */
48
+ export interface OwnedInstanceAsar {
49
+ /** Absolute path to the cached/source asar file. */
50
+ readonly path: string;
51
+ /** The asar's `x.y.z` version. */
52
+ readonly version: string;
53
+ }
54
+ /**
55
+ * Configuration for a harness-owned, isolated Obsidian instance.
56
+ *
57
+ * When present, the transport launches and owns its own Obsidian process
58
+ * against an isolated user-data dir instead of attaching to a running instance.
59
+ */
60
+ export interface OwnedInstanceConfig {
61
+ /** Optional asar to provision into {@link userDataDir} before launch. */
62
+ readonly asar?: OwnedInstanceAsar | undefined;
63
+ /** Absolute path to the Obsidian shell executable to launch. */
64
+ readonly exePath: string;
65
+ /**
66
+ * Absolute path to the isolated user-data dir. Created and owned by the
67
+ * transport, and deleted on dispose.
68
+ */
69
+ readonly userDataDir: string;
38
70
  }
39
71
  /**
40
72
  * Transport that communicates with Desktop Obsidian via Chrome DevTools Protocol.
@@ -48,10 +80,13 @@ export declare class DesktopCdpTransport implements ObsidianTransport {
48
80
  */
49
81
  readonly isMobile = false;
50
82
  private activeVaultPath;
51
- private readonly cdpPort;
52
- private readonly cdpUrl;
83
+ private readonly cdpHost;
84
+ private cdpPort;
85
+ private cdpUrl;
53
86
  private readonly commandTimeoutInMilliseconds;
54
87
  private messageId;
88
+ private readonly ownedConfig;
89
+ private ownedInstance;
55
90
  private ws;
56
91
  /**
57
92
  * Creates a new CDP transport.
@@ -60,9 +95,19 @@ export declare class DesktopCdpTransport implements ObsidianTransport {
60
95
  */
61
96
  constructor(config?: DesktopCdpTransportConfig);
62
97
  /**
63
- * Disposes of the active WebSocket connection.
98
+ * Disposes of the active WebSocket connection and, in owned-instance mode,
99
+ * kills the owned Obsidian process and removes its isolated user-data dir.
100
+ *
101
+ * The removal is retried because Windows briefly holds the just-killed
102
+ * process's file handles, which would otherwise fail `rmSync` with `EPERM`.
64
103
  */
65
104
  dispose(): Promise<void>;
105
+ /**
106
+ * Synchronous disposal — kills the owned instance and makes a best-effort
107
+ * removal of its user-data dir. Safe to call from a process `exit` handler
108
+ * (where async retries are impossible; a leftover temp dir is acceptable).
109
+ */
110
+ disposeSync(): void;
66
111
  /**
67
112
  * Evaluates a JavaScript expression inside Obsidian via CDP `Runtime.evaluate`.
68
113
  *
@@ -170,6 +215,15 @@ export declare class DesktopCdpTransport implements ObsidianTransport {
170
215
  * @returns The vault's base path.
171
216
  */
172
217
  private probeVaultPath;
218
+ /**
219
+ * Launches and connects to a harness-owned, isolated Obsidian instance for a
220
+ * vault: provisions the asar (if any), pre-seeds the isolated `obsidian.json`
221
+ * so the vault opens directly, launches the instance on a free CDP port, then
222
+ * waits until the vault window is ready and dismisses the trust dialog.
223
+ *
224
+ * @param vaultPath - The absolute path to the vault folder.
225
+ */
226
+ private registerVaultInOwnedInstance;
173
227
  /**
174
228
  * Sends a CDP command over WebSocket and waits for the response.
175
229
  *
@@ -192,4 +246,11 @@ export declare class DesktopCdpTransport implements ObsidianTransport {
192
246
  * @param vaultPath - The vault path to evaluate in.
193
247
  */
194
248
  private waitForLayoutReady;
249
+ /**
250
+ * Polls the owned instance until the vault target exists, layout is ready, and
251
+ * the trust dialog (if any) has been dismissed.
252
+ *
253
+ * @param vaultPath - The absolute path to the vault folder.
254
+ */
255
+ private waitForOwnedVaultReady;
195
256
  }