obsidian-launcher 2.1.1 → 2.1.2

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.
@@ -11,45 +11,57 @@ var _promisepool = require('@supercharge/promise-pool');
11
11
  var _lodash = require('lodash'); var _lodash2 = _interopRequireDefault(_lodash);
12
12
  async function fileExists(path6) {
13
13
  try {
14
- await _promises2.default.access(path6);
14
+ await _promises2.default.stat(path6);
15
15
  return true;
16
- } catch (e2) {
17
- return false;
16
+ } catch (e) {
17
+ if (_optionalChain([e, 'optionalAccess', _5 => _5.code]) == "ENOENT") {
18
+ return false;
19
+ }
20
+ throw e;
18
21
  }
19
22
  }
20
23
  async function makeTmpDir(prefix) {
21
24
  return _promises2.default.mkdtemp(_path2.default.join(_os2.default.tmpdir(), _nullishCoalesce(prefix, () => ( "tmp-"))));
22
25
  }
23
26
  async function atomicCreate(dest, func, opts = {}) {
27
+ const { replace = true, preserveTmpDir = false } = opts;
24
28
  dest = _path2.default.resolve(dest);
25
- const createdParentDir = await _promises2.default.mkdir(_path2.default.dirname(dest), { recursive: true });
26
- const tmpDir = await _promises2.default.mkdtemp(_path2.default.join(_path2.default.dirname(dest), `.${_path2.default.basename(dest)}.tmp.`));
27
- let success = false;
29
+ const parentDir = _path2.default.dirname(dest);
30
+ if (!replace && await fileExists(dest)) return;
31
+ await _promises2.default.mkdir(parentDir, { recursive: true });
32
+ const scratch = await _promises2.default.mkdtemp(_path2.default.join(parentDir, `.${_path2.default.basename(dest)}.tmp.`));
28
33
  try {
29
- let result = await _asyncNullishCoalesce(await func(tmpDir), async () => ( tmpDir));
30
- result = _path2.default.resolve(tmpDir, result);
31
- if (!result.startsWith(tmpDir)) {
32
- throw new Error(`Returned path ${result} not under tmpDir`);
34
+ let result = await _asyncNullishCoalesce(await func(scratch), async () => ( scratch));
35
+ result = _path2.default.resolve(scratch, result);
36
+ if (!result.startsWith(scratch)) {
37
+ throw new Error(`Returned path ${result} not under scratch`);
33
38
  }
34
- if (await fileExists(dest) && (await _promises2.default.stat(dest)).isDirectory()) {
35
- await _promises2.default.rename(dest, tmpDir + ".old");
39
+ if (replace) {
40
+ if (await _asyncOptionalChain([(await _promises2.default.stat(dest).catch(() => null)), 'optionalAccess', async _6 => _6.isDirectory, 'call', async _7 => _7()])) {
41
+ await _promises2.default.rename(dest, `${scratch}.old`);
42
+ }
43
+ await _promises2.default.rename(result, dest);
44
+ } else {
45
+ if (!await fileExists(dest)) {
46
+ await _promises2.default.rename(result, dest).catch((e) => {
47
+ if (_optionalChain([e, 'optionalAccess', _8 => _8.code]) != "ENOTEMPTY") throw e;
48
+ });
49
+ }
36
50
  }
37
- await _promises2.default.rename(result, dest);
38
- success = true;
39
- } finally {
40
- if (success) {
41
- await _promises2.default.rm(tmpDir + ".old", { recursive: true, force: true });
42
- await _promises2.default.rm(tmpDir, { recursive: true, force: true });
43
- } else if (!opts.preserveTmpDir) {
44
- await _promises2.default.rm(_nullishCoalesce(createdParentDir, () => ( tmpDir)), { recursive: true, force: true });
51
+ await _promises2.default.rm(scratch, { recursive: true, force: true });
52
+ await _promises2.default.rm(`${scratch}.old`, { recursive: true, force: true });
53
+ } catch (e) {
54
+ if (!preserveTmpDir) {
55
+ await _promises2.default.rm(scratch, { recursive: true, force: true });
45
56
  }
57
+ throw e;
46
58
  }
47
59
  }
48
60
  async function linkOrCp(src, dest) {
49
61
  await _promises2.default.rm(dest, { recursive: true, force: true });
50
62
  try {
51
63
  await _promises2.default.link(src, dest);
52
- } catch (e3) {
64
+ } catch (e2) {
53
65
  await _promises2.default.copyFile(src, dest);
54
66
  }
55
67
  }
@@ -168,38 +180,43 @@ async function fetchGitHubAPIPaginated(url, params = {}) {
168
180
  while (next) {
169
181
  const response = await fetchGitHubAPI(next);
170
182
  results.push(...await response.json());
171
- next = _optionalChain([parseLinkHeader, 'call', _5 => _5(_nullishCoalesce(response.headers.get("link"), () => ( ""))), 'access', _6 => _6.next, 'optionalAccess', _7 => _7.url]);
183
+ next = _optionalChain([parseLinkHeader, 'call', _9 => _9(_nullishCoalesce(response.headers.get("link"), () => ( ""))), 'access', _10 => _10.next, 'optionalAccess', _11 => _11.url]);
172
184
  }
173
185
  return results;
174
186
  }
175
187
  async function obsidianApiLogin(opts) {
176
188
  const { interactive = false, savePath } = opts;
177
- if (savePath) _dotenv2.default.config({ path: [savePath], quiet: true });
178
- let email = _process.env.OBSIDIAN_EMAIL;
179
- let password = _process.env.OBSIDIAN_PASSWORD;
189
+ const cached = savePath ? _dotenv2.default.parse(await _promises2.default.readFile(savePath).catch(() => "")) : {};
190
+ let email = _nullishCoalesce(_process.env.OBSIDIAN_EMAIL, () => ( cached.OBSIDIAN_EMAIL));
191
+ let password = _nullishCoalesce(_process.env.OBSIDIAN_PASSWORD, () => ( cached.OBSIDIAN_PASSWORD));
192
+ let promptedCredentials = false;
180
193
  if (!email || !password) {
181
194
  if (interactive) {
182
195
  console.log("Obsidian Insiders account is required to download Obsidian beta versions.");
183
196
  email = email || _readlinesync2.default.question("Obsidian email: ");
184
197
  password = password || _readlinesync2.default.question("Obsidian password: ", { hideEchoBack: true });
198
+ promptedCredentials = true;
185
199
  } else {
186
200
  throw Error(
187
201
  "Obsidian Insiders account is required to download Obsidian beta versions. Either set the OBSIDIAN_EMAIL and OBSIDIAN_PASSWORD env vars (.env file is supported) or pre-download the Obsidian beta with `npx obsidian-launcher download app -v <version>`"
188
202
  );
189
203
  }
190
204
  }
205
+ function parseSignin(r) {
206
+ return { token: r.token ? "token" : void 0, error: _optionalChain([r, 'access', _12 => _12.error, 'optionalAccess', _13 => _13.toString, 'call', _14 => _14()]), license: r.license };
207
+ }
191
208
  let needsMfa = false;
192
209
  let retries = 0;
193
210
  let signin = void 0;
194
- while (!_optionalChain([signin, 'optionalAccess', _8 => _8.token]) && retries < 3) {
211
+ while (!_optionalChain([signin, 'optionalAccess', _15 => _15.token]) && retries < 3) {
195
212
  if (retries > 0 || _process.env.CI) {
196
- await sleep(2 * Math.random() + retries * retries * 2);
213
+ await sleep(2 * Math.random() + retries * retries * 3);
197
214
  }
198
215
  let mfa = "";
199
216
  if (needsMfa && interactive) {
200
217
  mfa = _readlinesync2.default.question("Obsidian 2FA: ");
201
218
  }
202
- signin = await fetch("https://api.obsidian.md/user/signin", {
219
+ const response = await fetch("https://api.obsidian.md/user/signin", {
203
220
  method: "post",
204
221
  headers: {
205
222
  "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36",
@@ -208,27 +225,29 @@ async function obsidianApiLogin(opts) {
208
225
  },
209
226
  body: JSON.stringify({ email, password, mfa })
210
227
  }).then((r) => r.json());
211
- const error = _optionalChain([signin, 'access', _9 => _9.error, 'optionalAccess', _10 => _10.toLowerCase, 'call', _11 => _11()]);
212
- if (_optionalChain([error, 'optionalAccess', _12 => _12.includes, 'call', _13 => _13("2fa")]) && !needsMfa) {
228
+ signin = parseSignin(response);
229
+ const error = _optionalChain([signin, 'access', _16 => _16.error, 'optionalAccess', _17 => _17.toLowerCase, 'call', _18 => _18()]);
230
+ if (_optionalChain([error, 'optionalAccess', _19 => _19.includes, 'call', _20 => _20("2fa")]) && !needsMfa) {
213
231
  needsMfa = true;
214
232
  if (!interactive) {
215
233
  throw Error(
216
234
  "Can't login with 2FA in a non-interactive session. To download Obsidian beta versions, either disable 2FA on your account or pre-download the Obsidian beta with `npx obsidian-launcher download app -v <version>`"
217
235
  );
218
236
  }
219
- } else if (["please wait", "try again"].some((m) => _optionalChain([error, 'optionalAccess', _14 => _14.includes, 'call', _15 => _15(m)]))) {
237
+ } else if (["please wait", "try again"].some((m) => _optionalChain([error, 'optionalAccess', _21 => _21.includes, 'call', _22 => _22(m)]))) {
220
238
  console.warn(`Obsidian login failed: ${signin.error}`);
239
+ console.warn("Retrying obsidian login...");
221
240
  retries++;
222
241
  } else if (!signin.token) {
223
242
  throw Error(`Obsidian login failed: ${_nullishCoalesce(signin.error, () => ( "unknown error"))}`);
224
243
  }
225
244
  }
226
- if (!_optionalChain([signin, 'optionalAccess', _16 => _16.token])) {
227
- throw Error(`Obsidian login failed: ${_nullishCoalesce(_optionalChain([signin, 'optionalAccess', _17 => _17.error]), () => ( "unknown error"))}`);
228
- } else if (!_optionalChain([signin, 'optionalAccess', _18 => _18.license])) {
245
+ if (!_optionalChain([signin, 'optionalAccess', _23 => _23.token])) {
246
+ throw Error(`Obsidian login failed: ${_nullishCoalesce(_optionalChain([signin, 'optionalAccess', _24 => _24.error]), () => ( "unknown error"))}`);
247
+ } else if (!_optionalChain([signin, 'optionalAccess', _25 => _25.license])) {
229
248
  throw Error("Obsidian Insiders account is required to download Obsidian beta versions");
230
249
  }
231
- if (interactive && savePath && (!_process.env.OBSIDIAN_EMAIL || !_process.env.OBSIDIAN_PASSWORD)) {
250
+ if (savePath && promptedCredentials) {
232
251
  const save = _readlinesync2.default.question("Cache credentails to disk? [y/n]: ");
233
252
  if (["y", "yes"].includes(save.toLowerCase())) {
234
253
  await _promises2.default.writeFile(
@@ -243,6 +262,9 @@ OBSIDIAN_PASSWORD='${password}'
243
262
  return signin.token;
244
263
  }
245
264
  async function fetchObsidianApi(url, opts) {
265
+ if (!opts.token) {
266
+ throw Error("Obsidian credentials required to download Obsidian beta release");
267
+ }
246
268
  url = createURL(url, "https://releases.obsidian.md");
247
269
  const response = await fetch(url, {
248
270
  headers: {
@@ -349,7 +371,7 @@ var ChromeLocalStorage = class {
349
371
  var _zlib = require('zlib'); var _zlib2 = _interopRequireDefault(_zlib);
350
372
 
351
373
  function normalizeGitHubRepo(repo) {
352
- return _nullishCoalesce(_optionalChain([repo, 'access', _19 => _19.match, 'call', _20 => _20(/^(https?:\/\/)?(github.com\/)?(.*?)\/?$/), 'optionalAccess', _21 => _21[3]]), () => ( repo));
374
+ return _nullishCoalesce(_optionalChain([repo, 'access', _26 => _26.match, 'call', _27 => _27(/^(https?:\/\/)?(github.com\/)?(.*?)\/?$/), 'optionalAccess', _28 => _28[3]]), () => ( repo));
353
375
  }
354
376
  async function extractGz(archive, dest) {
355
377
  await _promises3.pipeline.call(void 0, _fs2.default.createReadStream(archive), _zlib2.default.createGunzip(), _fs2.default.createWriteStream(dest));
@@ -374,16 +396,16 @@ ${stderr}`);
374
396
  return result;
375
397
  }
376
398
  async function extractObsidianAppImage(appImage, dest) {
377
- await atomicCreate(dest, async (tmpDir) => {
378
- await sevenZ(["x", "-o.", _path2.default.relative(tmpDir, appImage)], { cwd: tmpDir });
379
- return tmpDir;
399
+ await atomicCreate(dest, async (scratch) => {
400
+ await sevenZ(["x", "-o.", _path2.default.relative(scratch, appImage)], { cwd: scratch });
401
+ return scratch;
380
402
  });
381
403
  }
382
404
  async function extractObsidianTar(tar, dest) {
383
- await atomicCreate(dest, async (tmpDir) => {
384
- await extractGz(tar, _path2.default.join(tmpDir, "inflated.tar"));
385
- await sevenZ(["x", "-o.", "inflated.tar"], { cwd: tmpDir });
386
- return (await _promises2.default.readdir(tmpDir)).find((p) => p.match("obsidian-"));
405
+ await atomicCreate(dest, async (scratch) => {
406
+ await extractGz(tar, _path2.default.join(scratch, "inflated.tar"));
407
+ await sevenZ(["x", "-o.", "inflated.tar"], { cwd: scratch });
408
+ return (await _promises2.default.readdir(scratch)).find((p) => p.match("obsidian-"));
387
409
  });
388
410
  }
389
411
  async function extractObsidianExe(exe, arch, dest) {
@@ -397,17 +419,17 @@ async function extractObsidianExe(exe, arch, dest) {
397
419
  } else {
398
420
  throw Error(`No Obsidian installer found for ${process.platform} ${process.arch}`);
399
421
  }
400
- await atomicCreate(dest, async (tmpDir) => {
401
- await sevenZ(["x", "-oinstaller", _path2.default.relative(tmpDir, exe), subArchive], { cwd: tmpDir });
402
- await sevenZ(["x", "-oobsidian", _path2.default.join("installer", subArchive)], { cwd: tmpDir });
422
+ await atomicCreate(dest, async (scratch) => {
423
+ await sevenZ(["x", "-oinstaller", _path2.default.relative(scratch, exe), subArchive], { cwd: scratch });
424
+ await sevenZ(["x", "-oobsidian", _path2.default.join("installer", subArchive)], { cwd: scratch });
403
425
  return "obsidian";
404
426
  });
405
427
  }
406
428
  async function extractObsidianDmg(dmg, dest) {
407
429
  dest = _path2.default.resolve(dest);
408
- await atomicCreate(dest, async (tmpDir) => {
409
- await sevenZ(["x", "-o.", _path2.default.relative(tmpDir, dmg), "*/Obsidian.app", "Obsidian.app"], { cwd: tmpDir });
410
- const files = await _promises2.default.readdir(tmpDir);
430
+ await atomicCreate(dest, async (scratch) => {
431
+ await sevenZ(["x", "-o.", _path2.default.relative(scratch, dmg), "*/Obsidian.app", "Obsidian.app"], { cwd: scratch });
432
+ const files = await _promises2.default.readdir(scratch);
411
433
  if (files.includes("Obsidian.app")) {
412
434
  return "Obsidian.app";
413
435
  } else {
@@ -430,8 +452,8 @@ async function fetchObsidianDesktopReleases(sinceDate, sinceSha) {
430
452
  commitHistory,
431
453
  (commit) => fetch(`https://raw.githubusercontent.com/${repo}/${commit.sha}/desktop-releases.json`).then((r) => r.json())
432
454
  );
433
- const commitDate = _nullishCoalesce(_optionalChain([commitHistory, 'access', _22 => _22.at, 'call', _23 => _23(-1), 'optionalAccess', _24 => _24.commit, 'access', _25 => _25.committer, 'access', _26 => _26.date]), () => ( sinceDate));
434
- const commitSha = _nullishCoalesce(_optionalChain([commitHistory, 'access', _27 => _27.at, 'call', _28 => _28(-1), 'optionalAccess', _29 => _29.sha]), () => ( sinceSha));
455
+ const commitDate = _nullishCoalesce(_optionalChain([commitHistory, 'access', _29 => _29.at, 'call', _30 => _30(-1), 'optionalAccess', _31 => _31.commit, 'access', _32 => _32.committer, 'access', _33 => _33.date]), () => ( sinceDate));
456
+ const commitSha = _nullishCoalesce(_optionalChain([commitHistory, 'access', _34 => _34.at, 'call', _35 => _35(-1), 'optionalAccess', _36 => _36.sha]), () => ( sinceSha));
435
457
  return [fileHistory, { commitDate, commitSha }];
436
458
  }
437
459
  async function fetchObsidianGitHubReleases() {
@@ -489,14 +511,14 @@ function parseObsidianGithubRelease(gitHubRelease) {
489
511
  version,
490
512
  gitHubRelease: gitHubRelease.html_url,
491
513
  downloads: {
492
- asar: _optionalChain([asar, 'optionalAccess', _30 => _30.url]),
493
- appImage: _optionalChain([appImage, 'optionalAccess', _31 => _31.url]),
494
- appImageArm: _optionalChain([appImageArm, 'optionalAccess', _32 => _32.url]),
495
- tar: _optionalChain([tar, 'optionalAccess', _33 => _33.url]),
496
- tarArm: _optionalChain([tarArm, 'optionalAccess', _34 => _34.url]),
497
- dmg: _optionalChain([dmg, 'optionalAccess', _35 => _35.url]),
498
- exe: _optionalChain([exe, 'optionalAccess', _36 => _36.url]),
499
- apk: _optionalChain([apk, 'optionalAccess', _37 => _37.url])
514
+ asar: _optionalChain([asar, 'optionalAccess', _37 => _37.url]),
515
+ appImage: _optionalChain([appImage, 'optionalAccess', _38 => _38.url]),
516
+ appImageArm: _optionalChain([appImageArm, 'optionalAccess', _39 => _39.url]),
517
+ tar: _optionalChain([tar, 'optionalAccess', _40 => _40.url]),
518
+ tarArm: _optionalChain([tarArm, 'optionalAccess', _41 => _41.url]),
519
+ dmg: _optionalChain([dmg, 'optionalAccess', _42 => _42.url]),
520
+ exe: _optionalChain([exe, 'optionalAccess', _43 => _43.url]),
521
+ apk: _optionalChain([apk, 'optionalAccess', _44 => _44.url])
500
522
  },
501
523
  installers: {
502
524
  appImage: appImage ? { digest: appImage.digest } : void 0,
@@ -532,8 +554,8 @@ function updateObsidianVersionList(args) {
532
554
  const parsed = parseObsidianGithubRelease(githubRelease);
533
555
  const newVersion = _lodash2.default.merge(_nullishCoalesce(newVersions[parsed.version], () => ( {})), parsed);
534
556
  for (const installerKey of INSTALLER_KEYS) {
535
- const oldDigest = _optionalChain([oldVersions, 'access', _38 => _38[parsed.version], 'optionalAccess', _39 => _39.installers, 'access', _40 => _40[installerKey], 'optionalAccess', _41 => _41.digest]);
536
- const newDigest = _optionalChain([newVersion, 'access', _42 => _42.installers, 'optionalAccess', _43 => _43[installerKey], 'optionalAccess', _44 => _44.digest]);
557
+ const oldDigest = _optionalChain([oldVersions, 'access', _45 => _45[parsed.version], 'optionalAccess', _46 => _46.installers, 'access', _47 => _47[installerKey], 'optionalAccess', _48 => _48.digest]);
558
+ const newDigest = _optionalChain([newVersion, 'access', _49 => _49.installers, 'optionalAccess', _50 => _50[installerKey], 'optionalAccess', _51 => _51.digest]);
537
559
  if (oldDigest && oldDigest != newDigest) {
538
560
  newVersion.installers[installerKey] = { digest: newDigest };
539
561
  }
@@ -550,7 +572,11 @@ function updateObsidianVersionList(args) {
550
572
  minInstallerVersion = version;
551
573
  }
552
574
  }
553
- newVersions[version] = _lodash2.default.merge({ minInstallerVersion, maxInstallerVersion }, newVersions[version]);
575
+ newVersions[version] = _lodash2.default.merge(newVersions[version], {
576
+ minInstallerVersion: _nullishCoalesce(_optionalChain([newVersions, 'access', _52 => _52[version], 'optionalAccess', _53 => _53.minInstallerVersion]), () => ( minInstallerVersion)),
577
+ maxInstallerVersion
578
+ // override maxInstallerVersion if it was already set
579
+ });
554
580
  }
555
581
  for (const installerInfo of installerInfos) {
556
582
  newVersions[installerInfo.version] = _lodash2.default.merge(_nullishCoalesce(newVersions[installerInfo.version], () => ( {})), {
@@ -618,8 +644,8 @@ async function extractInstallerInfo(installerKey, url) {
618
644
  }
619
645
  function normalizeObsidianVersionInfo(versionInfo) {
620
646
  versionInfo = _lodash2.default.cloneDeep(versionInfo);
621
- versionInfo.electronVersion = _optionalChain([versionInfo, 'access', _45 => _45.installers, 'optionalAccess', _46 => _46.appImage, 'optionalAccess', _47 => _47.electron]);
622
- versionInfo.chromeVersion = _optionalChain([versionInfo, 'access', _48 => _48.installers, 'optionalAccess', _49 => _49.appImage, 'optionalAccess', _50 => _50.chrome]);
647
+ versionInfo.electronVersion = _optionalChain([versionInfo, 'access', _54 => _54.installers, 'optionalAccess', _55 => _55.appImage, 'optionalAccess', _56 => _56.electron]);
648
+ versionInfo.chromeVersion = _optionalChain([versionInfo, 'access', _57 => _57.installers, 'optionalAccess', _58 => _58.appImage, 'optionalAccess', _59 => _59.chrome]);
623
649
  versionInfo.downloads = _nullishCoalesce(versionInfo.downloads, () => ( {}));
624
650
  versionInfo.installers = _nullishCoalesce(versionInfo.installers, () => ( {}));
625
651
  const canonicalForm = {
@@ -691,7 +717,7 @@ var ObsidianLauncher = class {
691
717
  if (!(dest in this.metadataCache)) {
692
718
  let data;
693
719
  let error;
694
- const cacheMtime = await _asyncOptionalChain([(await _promises2.default.stat(dest).catch(() => void 0)), 'optionalAccess', async _51 => _51.mtime]);
720
+ const cacheMtime = await _asyncOptionalChain([(await _promises2.default.stat(dest).catch(() => void 0)), 'optionalAccess', async _60 => _60.mtime]);
695
721
  if (url.startsWith("file:")) {
696
722
  data = JSON.parse(await _promises2.default.readFile(_url.fileURLToPath.call(void 0, url), "utf-8"));
697
723
  }
@@ -709,10 +735,10 @@ var ObsidianLauncher = class {
709
735
  return d;
710
736
  }));
711
737
  if (response.success) {
712
- await atomicCreate(dest, async (tmpDir) => {
713
- await _promises2.default.writeFile(_path2.default.join(tmpDir, "download.json"), response.result);
714
- return _path2.default.join(tmpDir, "download.json");
715
- });
738
+ await atomicCreate(dest, async (scratch) => {
739
+ await _promises2.default.writeFile(_path2.default.join(scratch, "download.json"), response.result);
740
+ return _path2.default.join(scratch, "download.json");
741
+ }, { replace: true });
716
742
  data = JSON.parse(response.result);
717
743
  } else {
718
744
  error = response.error;
@@ -779,7 +805,7 @@ var ObsidianLauncher = class {
779
805
  * Resolves Obsidian app and installer version strings to absolute versions.
780
806
  * @param appVersion specific version or one of
781
807
  * - "latest": Get the current latest non-beta Obsidian version
782
- * - "latest-beta": Get the current latest beta Obsidian version (or latest is there is no current beta)
808
+ * - "latest-beta": Get the current latest beta Obsidian version (or latest if there is no current beta)
783
809
  * - "earliest": Get the `minAppVersion` set in your `manifest.json`
784
810
  * @param installerVersion specific version or one of
785
811
  * - "latest": Get the latest Obsidian installer compatible with `appVersion`
@@ -837,7 +863,7 @@ var ObsidianLauncher = class {
837
863
  appVersion = versions.filter((v) => !v.isBeta).at(-1).version;
838
864
  } else if (appVersion == "earliest") {
839
865
  const manifest = await this.getRootManifest();
840
- if (!_optionalChain([manifest, 'optionalAccess', _52 => _52.minAppVersion])) {
866
+ if (!_optionalChain([manifest, 'optionalAccess', _61 => _61.minAppVersion])) {
841
867
  throw Error('Unable to resolve Obsidian appVersion "earliest", no manifest.json or minAppVersion found.');
842
868
  }
843
869
  appVersion = manifest.minAppVersion;
@@ -913,31 +939,29 @@ var ObsidianLauncher = class {
913
939
  const versionInfo = await this.getVersionInfo(installerVersion);
914
940
  installerVersion = versionInfo.version;
915
941
  const installerInfo = await this.getInstallerInfo(installerVersion, { platform, arch });
916
- const cacheDir = _path2.default.join(this.cacheDir, `obsidian-installer/${platform}-${arch}/Obsidian-${installerVersion}`);
942
+ const installerDir = _path2.default.join(this.cacheDir, `obsidian-installer/${platform}-${arch}/Obsidian-${installerVersion}`);
917
943
  let binaryPath;
918
944
  let extractor;
919
945
  if (platform == "linux") {
920
- binaryPath = _path2.default.join(cacheDir, "obsidian");
946
+ binaryPath = _path2.default.join(installerDir, "obsidian");
921
947
  extractor = (installer, dest) => extractObsidianAppImage(installer, dest);
922
948
  } else if (platform == "win32") {
923
- binaryPath = _path2.default.join(cacheDir, "Obsidian.exe");
949
+ binaryPath = _path2.default.join(installerDir, "Obsidian.exe");
924
950
  extractor = (installer, dest) => extractObsidianExe(installer, arch, dest);
925
951
  } else if (platform == "darwin") {
926
- binaryPath = _path2.default.join(cacheDir, "Contents/MacOS/Obsidian");
952
+ binaryPath = _path2.default.join(installerDir, "Contents/MacOS/Obsidian");
927
953
  extractor = (installer, dest) => extractObsidianDmg(installer, dest);
928
954
  } else {
929
955
  throw Error(`Unsupported platform ${platform}`);
930
956
  }
931
- if (!await fileExists(binaryPath)) {
957
+ await atomicCreate(installerDir, async (scratch) => {
932
958
  console.log(`Downloading Obsidian installer v${installerVersion}...`);
933
- await atomicCreate(cacheDir, async (tmpDir) => {
934
- const installer = _path2.default.join(tmpDir, "installer");
935
- await downloadResponse(await fetch(installerInfo.url), installer);
936
- const extracted = _path2.default.join(tmpDir, "extracted");
937
- await extractor(installer, extracted);
938
- return extracted;
939
- });
940
- }
959
+ const installer = _path2.default.join(scratch, "installer");
960
+ await downloadResponse(await fetch(installerInfo.url), installer);
961
+ const extracted = _path2.default.join(scratch, "extracted");
962
+ await extractor(installer, extracted);
963
+ return extracted;
964
+ }, { replace: false });
941
965
  return binaryPath;
942
966
  }
943
967
  /**
@@ -956,29 +980,27 @@ var ObsidianLauncher = class {
956
980
  throw Error(`No asar found for Obsidian version ${appVersion}`);
957
981
  }
958
982
  const appPath = _path2.default.join(this.cacheDir, "obsidian-app", `obsidian-${versionInfo.version}.asar`);
959
- if (!await fileExists(appPath)) {
960
- console.log(`Downloading Obsidian app v${versionInfo.version} ...`);
961
- await atomicCreate(appPath, async (tmpDir) => {
962
- const isInsiders = new URL(appUrl).hostname.endsWith(".obsidian.md");
963
- let response;
964
- if (isInsiders) {
965
- if (!this.obsidianApiToken) {
966
- this.obsidianApiToken = await obsidianApiLogin({
967
- interactive: this.interactive,
968
- savePath: _path2.default.join(this.cacheDir, "obsidian-credentials.env")
969
- });
970
- }
971
- response = await fetchObsidianApi(appUrl, { token: this.obsidianApiToken });
972
- } else {
973
- response = await fetch(appUrl);
974
- }
975
- const archive = _path2.default.join(tmpDir, "app.asar.gz");
976
- const asar = _path2.default.join(tmpDir, "app.asar");
977
- await downloadResponse(response, archive);
978
- await extractGz(archive, asar);
979
- return asar;
983
+ const isInsiders = new URL(appUrl).hostname.endsWith(".obsidian.md");
984
+ if (isInsiders && !this.obsidianApiToken && !await fileExists(appPath)) {
985
+ this.obsidianApiToken = await obsidianApiLogin({
986
+ interactive: this.interactive,
987
+ savePath: _path2.default.join(this.cacheDir, "obsidian-credentials.env")
980
988
  });
981
989
  }
990
+ await atomicCreate(appPath, async (scratch) => {
991
+ console.log(`Downloading Obsidian app v${versionInfo.version} ...`);
992
+ let response;
993
+ if (isInsiders) {
994
+ response = await fetchObsidianApi(appUrl, { token: this.obsidianApiToken });
995
+ } else {
996
+ response = await fetch(appUrl);
997
+ }
998
+ const archive = _path2.default.join(scratch, "app.asar.gz");
999
+ const asar = _path2.default.join(scratch, "app.asar");
1000
+ await downloadResponse(response, archive);
1001
+ await extractGz(archive, asar);
1002
+ return asar;
1003
+ }, { replace: false });
982
1004
  return appPath;
983
1005
  }
984
1006
  /**
@@ -995,26 +1017,24 @@ var ObsidianLauncher = class {
995
1017
  async downloadChromedriver(installerVersion, opts = {}) {
996
1018
  const { platform, arch } = _lodash2.default.defaults({}, opts, currentPlatform);
997
1019
  const installerInfo = await this.getInstallerInfo(installerVersion, { platform, arch });
998
- const cacheDir = _path2.default.join(this.cacheDir, `electron-chromedriver/${platform}-${arch}/${installerInfo.electron}`);
1020
+ const chromedriverDir = _path2.default.join(this.cacheDir, `electron-chromedriver/${platform}-${arch}/${installerInfo.electron}`);
999
1021
  let chromedriverPath;
1000
1022
  if (process.platform == "win32") {
1001
- chromedriverPath = _path2.default.join(cacheDir, `chromedriver.exe`);
1023
+ chromedriverPath = _path2.default.join(chromedriverDir, `chromedriver.exe`);
1002
1024
  } else {
1003
- chromedriverPath = _path2.default.join(cacheDir, `chromedriver`);
1025
+ chromedriverPath = _path2.default.join(chromedriverDir, `chromedriver`);
1004
1026
  }
1005
- if (!await fileExists(chromedriverPath)) {
1027
+ await atomicCreate(chromedriverDir, async (scratch) => {
1006
1028
  console.log(`Downloading chromedriver for electron ${installerInfo.electron} ...`);
1007
- await atomicCreate(cacheDir, async (tmpDir) => {
1008
- const chromedriverZipPath = await _get.downloadArtifact.call(void 0, {
1009
- version: installerInfo.electron,
1010
- artifactName: "chromedriver",
1011
- cacheRoot: _path2.default.join(tmpDir, "download")
1012
- });
1013
- const extracted = _path2.default.join(tmpDir, "extracted");
1014
- await _extractzip2.default.call(void 0, chromedriverZipPath, { dir: extracted });
1015
- return extracted;
1029
+ const chromedriverZipPath = await _get.downloadArtifact.call(void 0, {
1030
+ version: installerInfo.electron,
1031
+ artifactName: "chromedriver",
1032
+ cacheRoot: _path2.default.join(scratch, "download")
1016
1033
  });
1017
- }
1034
+ const extracted = _path2.default.join(scratch, "extracted");
1035
+ await _extractzip2.default.call(void 0, chromedriverZipPath, { dir: extracted });
1036
+ return extracted;
1037
+ }, { replace: false });
1018
1038
  return chromedriverPath;
1019
1039
  }
1020
1040
  /**
@@ -1029,14 +1049,12 @@ var ObsidianLauncher = class {
1029
1049
  );
1030
1050
  }
1031
1051
  const apkPath = _path2.default.join(this.cacheDir, "obsidian-apk", `obsidian-${versionInfo.version}.apk`);
1032
- if (!await fileExists(apkPath)) {
1052
+ await atomicCreate(apkPath, async (scratch) => {
1033
1053
  console.log(`Downloading Obsidian apk v${versionInfo.version} ...`);
1034
- await atomicCreate(apkPath, async (tmpDir) => {
1035
- const dest = _path2.default.join(tmpDir, "obsidian.apk");
1036
- await downloadResponse(await fetch(apkUrl), dest);
1037
- return dest;
1038
- });
1039
- }
1054
+ const dest = _path2.default.join(scratch, "obsidian.apk");
1055
+ await downloadResponse(await fetch(apkUrl), dest);
1056
+ return dest;
1057
+ }, { replace: false });
1040
1058
  return apkPath;
1041
1059
  }
1042
1060
  /** Gets the latest version of a plugin. */
@@ -1063,23 +1081,21 @@ var ObsidianLauncher = class {
1063
1081
  }
1064
1082
  version = _semver2.default.valid(version);
1065
1083
  const pluginDir = _path2.default.join(this.cacheDir, "obsidian-plugins", repo, version);
1066
- if (!await fileExists(pluginDir)) {
1067
- await atomicCreate(pluginDir, async (tmpDir) => {
1068
- const assetsToDownload = { "manifest.json": true, "main.js": true, "styles.css": false };
1069
- await Promise.all(
1070
- Object.entries(assetsToDownload).map(async ([file, required]) => {
1071
- const url = `https://github.com/${repo}/releases/download/${version}/${file}`;
1072
- const response = await fetch(url);
1073
- if (response.ok) {
1074
- await downloadResponse(response, _path2.default.join(tmpDir, file));
1075
- } else if (required) {
1076
- throw Error(`No ${file} found for ${repo} version ${version}`);
1077
- }
1078
- })
1079
- );
1080
- return tmpDir;
1081
- });
1082
- }
1084
+ await atomicCreate(pluginDir, async (scratch) => {
1085
+ const assetsToDownload = { "manifest.json": true, "main.js": true, "styles.css": false };
1086
+ await Promise.all(
1087
+ Object.entries(assetsToDownload).map(async ([file, required]) => {
1088
+ const url = `https://github.com/${repo}/releases/download/${version}/${file}`;
1089
+ const response = await fetch(url);
1090
+ if (response.ok) {
1091
+ await downloadResponse(response, _path2.default.join(scratch, file));
1092
+ } else if (required) {
1093
+ throw Error(`No ${file} found for ${repo} version ${version}`);
1094
+ }
1095
+ })
1096
+ );
1097
+ return scratch;
1098
+ }, { replace: false });
1083
1099
  return pluginDir;
1084
1100
  }
1085
1101
  /**
@@ -1231,31 +1247,29 @@ var ObsidianLauncher = class {
1231
1247
  }
1232
1248
  version = _semver2.default.valid(version);
1233
1249
  const themeDir = _path2.default.join(this.cacheDir, "obsidian-themes", repo, version);
1234
- if (!await fileExists(themeDir)) {
1235
- await atomicCreate(themeDir, async (tmpDir) => {
1236
- const assetsToDownload = ["manifest.json", "theme.css"];
1237
- let baseUrl = `https://github.com/${repo}/releases/download/${version}`;
1238
- if (!(await fetch(`${baseUrl}/manifest.json`)).ok) {
1239
- if (version != latest) {
1240
- throw Error(`No theme version "${version}" found`);
1241
- }
1242
- baseUrl = `https://raw.githubusercontent.com/${repo}/HEAD`;
1250
+ await atomicCreate(themeDir, async (scratch) => {
1251
+ const assetsToDownload = ["manifest.json", "theme.css"];
1252
+ let baseUrl = `https://github.com/${repo}/releases/download/${version}`;
1253
+ if (!(await fetch(`${baseUrl}/manifest.json`)).ok) {
1254
+ if (version != latest) {
1255
+ throw Error(`No theme version "${version}" found`);
1243
1256
  }
1244
- await Promise.all(
1245
- assetsToDownload.map(
1246
- async (file) => {
1247
- const url = `${baseUrl}/${file}`;
1248
- const response = await fetch(url);
1249
- if (response.ok) {
1250
- await downloadResponse(response, _path2.default.join(tmpDir, file));
1251
- } else {
1252
- throw Error(`No ${file} found for ${repo}`);
1253
- }
1257
+ baseUrl = `https://raw.githubusercontent.com/${repo}/HEAD`;
1258
+ }
1259
+ await Promise.all(
1260
+ assetsToDownload.map(
1261
+ async (file) => {
1262
+ const url = `${baseUrl}/${file}`;
1263
+ const response = await fetch(url);
1264
+ if (response.ok) {
1265
+ await downloadResponse(response, _path2.default.join(scratch, file));
1266
+ } else {
1267
+ throw Error(`No ${file} found for ${repo}`);
1254
1268
  }
1255
- )
1256
- );
1257
- });
1258
- }
1269
+ }
1270
+ )
1271
+ );
1272
+ }, { replace: false });
1259
1273
  return themeDir;
1260
1274
  }
1261
1275
  /**
@@ -1501,16 +1515,16 @@ var ObsidianLauncher = class {
1501
1515
  async updateVersionList(original, opts = {}) {
1502
1516
  const { maxInstances = 1 } = opts;
1503
1517
  const [destkopReleases, commitInfo] = await fetchObsidianDesktopReleases(
1504
- _optionalChain([original, 'optionalAccess', _53 => _53.metadata, 'access', _54 => _54.commitDate]),
1505
- _optionalChain([original, 'optionalAccess', _55 => _55.metadata, 'access', _56 => _56.commitSha])
1518
+ _optionalChain([original, 'optionalAccess', _62 => _62.metadata, 'access', _63 => _63.commitDate]),
1519
+ _optionalChain([original, 'optionalAccess', _64 => _64.metadata, 'access', _65 => _65.commitSha])
1506
1520
  );
1507
1521
  const gitHubReleases = await fetchObsidianGitHubReleases();
1508
1522
  let newVersions = updateObsidianVersionList({
1509
- original: _optionalChain([original, 'optionalAccess', _57 => _57.versions]),
1523
+ original: _optionalChain([original, 'optionalAccess', _66 => _66.versions]),
1510
1524
  destkopReleases,
1511
1525
  gitHubReleases
1512
1526
  });
1513
- const newInstallers = newVersions.flatMap((v) => INSTALLER_KEYS.map((k) => [v, k])).filter(([v, key]) => _optionalChain([v, 'access', _58 => _58.downloads, 'optionalAccess', _59 => _59[key]]) && !_optionalChain([v, 'access', _60 => _60.installers, 'optionalAccess', _61 => _61[key], 'optionalAccess', _62 => _62.chrome]));
1527
+ const newInstallers = newVersions.flatMap((v) => INSTALLER_KEYS.map((k) => [v, k])).filter(([v, key]) => _optionalChain([v, 'access', _67 => _67.downloads, 'optionalAccess', _68 => _68[key]]) && !_optionalChain([v, 'access', _69 => _69.installers, 'optionalAccess', _70 => _70[key], 'optionalAccess', _71 => _71.chrome]));
1514
1528
  const installerInfos = await pool(maxInstances, newInstallers, async ([v, key]) => {
1515
1529
  const installerInfo = await extractInstallerInfo(key, v.downloads[key]);
1516
1530
  return { version: v.version, key, installerInfo };
@@ -1521,13 +1535,13 @@ var ObsidianLauncher = class {
1521
1535
  schemaVersion: obsidianVersionsSchemaVersion,
1522
1536
  commitDate: commitInfo.commitDate,
1523
1537
  commitSha: commitInfo.commitSha,
1524
- timestamp: _nullishCoalesce(_optionalChain([original, 'optionalAccess', _63 => _63.metadata, 'access', _64 => _64.timestamp]), () => ( ""))
1538
+ timestamp: _nullishCoalesce(_optionalChain([original, 'optionalAccess', _72 => _72.metadata, 'access', _73 => _73.timestamp]), () => ( ""))
1525
1539
  // set down below
1526
1540
  },
1527
1541
  versions: newVersions
1528
1542
  };
1529
1543
  const dayMs = 24 * 60 * 60 * 1e3;
1530
- const timeSinceLastUpdate = (/* @__PURE__ */ new Date()).getTime() - new Date(_nullishCoalesce(_optionalChain([original, 'optionalAccess', _65 => _65.metadata, 'access', _66 => _66.timestamp]), () => ( 0))).getTime();
1544
+ const timeSinceLastUpdate = (/* @__PURE__ */ new Date()).getTime() - new Date(_nullishCoalesce(_optionalChain([original, 'optionalAccess', _74 => _74.metadata, 'access', _75 => _75.timestamp]), () => ( 0))).getTime();
1531
1545
  if (!_lodash2.default.isEqual(original, result) || timeSinceLastUpdate > 29 * dayMs) {
1532
1546
  result.metadata.timestamp = (/* @__PURE__ */ new Date()).toISOString();
1533
1547
  }
@@ -1573,4 +1587,4 @@ var ObsidianLauncher = class {
1573
1587
 
1574
1588
 
1575
1589
  exports.watchFiles = watchFiles; exports.ObsidianLauncher = ObsidianLauncher;
1576
- //# sourceMappingURL=chunk-BLHP5CDO.cjs.map
1590
+ //# sourceMappingURL=chunk-Z5EOC6TG.cjs.map