obsidian-launcher 2.1.0 → 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.
- package/README.md +3 -3
- package/dist/{chunk-OUPK2DAJ.js → chunk-HMKNUWAY.js} +201 -159
- package/dist/chunk-HMKNUWAY.js.map +1 -0
- package/dist/{chunk-SG2CJVPK.cjs → chunk-Z5EOC6TG.cjs} +231 -189
- package/dist/chunk-Z5EOC6TG.cjs.map +1 -0
- package/dist/cli.cjs +9 -9
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +6 -6
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +9 -5
- package/dist/chunk-OUPK2DAJ.js.map +0 -1
- package/dist/chunk-SG2CJVPK.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ The primary use case for this package is to allow [wdio-obsidian-service](../wdi
|
|
|
7
7
|
## Example Usage
|
|
8
8
|
You can run the CLI via `npx`, e.g.:
|
|
9
9
|
```bash
|
|
10
|
-
npx obsidian-launcher watch --version 1.8.10 --copy
|
|
10
|
+
npx obsidian-launcher watch --version 1.8.10 --copy --plugin . test/vault
|
|
11
11
|
```
|
|
12
12
|
This will download and launch Obsidian 1.8.10 with a sandboxed configuration directory so you don't need to worry about it interfering with your system Obsidian installation. You can even launch multiple different versions of Obsidian side-by-side. See [below](#cli) for CLI docs.
|
|
13
13
|
|
|
@@ -32,7 +32,7 @@ Obsidian Desktop is distributed in two parts, the "installer" which is the execu
|
|
|
32
32
|
`appVersion` can be set to one of:
|
|
33
33
|
- a specific version string like "1.7.7"
|
|
34
34
|
- "latest": run the latest non-beta Obsidian version
|
|
35
|
-
- "latest-beta": run the latest beta Obsidian version (or latest
|
|
35
|
+
- "latest-beta": run the latest beta Obsidian version (or latest if there is no current beta)
|
|
36
36
|
- To download Obsidian beta versions you'll need to have an Obsidian Insiders account
|
|
37
37
|
- "earliest": run the `minAppVersion` set in your plugin's `manifest.json`
|
|
38
38
|
|
|
@@ -61,7 +61,7 @@ Several commands can take a list of plugins and themes to install. You can speci
|
|
|
61
61
|
- `id:<community-id>`: For plugins, id of a community plugin, e.g. `id:templater-obsidian`
|
|
62
62
|
- `name:<community-name>`: For themes, name of a community theme, e.g. `name:Minimal`
|
|
63
63
|
|
|
64
|
-
You can install a specific version of a plugin or theme with `-p id:myplugin
|
|
64
|
+
You can install a specific version of a plugin or theme with `-p id:myplugin@1.2.3`.
|
|
65
65
|
|
|
66
66
|
### launch
|
|
67
67
|
Download and launch Obsidian, opening the specified vault.
|
|
@@ -7,38 +7,50 @@ import { PromisePool } from "@supercharge/promise-pool";
|
|
|
7
7
|
import _ from "lodash";
|
|
8
8
|
async function fileExists(path6) {
|
|
9
9
|
try {
|
|
10
|
-
await fsAsync.
|
|
10
|
+
await fsAsync.stat(path6);
|
|
11
11
|
return true;
|
|
12
|
-
} catch {
|
|
13
|
-
|
|
12
|
+
} catch (e) {
|
|
13
|
+
if (e?.code == "ENOENT") {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
throw e;
|
|
14
17
|
}
|
|
15
18
|
}
|
|
16
19
|
async function makeTmpDir(prefix) {
|
|
17
20
|
return fsAsync.mkdtemp(path.join(os.tmpdir(), prefix ?? "tmp-"));
|
|
18
21
|
}
|
|
19
22
|
async function atomicCreate(dest, func, opts = {}) {
|
|
23
|
+
const { replace = true, preserveTmpDir = false } = opts;
|
|
20
24
|
dest = path.resolve(dest);
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
const parentDir = path.dirname(dest);
|
|
26
|
+
if (!replace && await fileExists(dest)) return;
|
|
27
|
+
await fsAsync.mkdir(parentDir, { recursive: true });
|
|
28
|
+
const scratch = await fsAsync.mkdtemp(path.join(parentDir, `.${path.basename(dest)}.tmp.`));
|
|
24
29
|
try {
|
|
25
|
-
let result = await func(
|
|
26
|
-
result = path.resolve(
|
|
27
|
-
if (!result.startsWith(
|
|
28
|
-
throw new Error(`Returned path ${result} not under
|
|
30
|
+
let result = await func(scratch) ?? scratch;
|
|
31
|
+
result = path.resolve(scratch, result);
|
|
32
|
+
if (!result.startsWith(scratch)) {
|
|
33
|
+
throw new Error(`Returned path ${result} not under scratch`);
|
|
29
34
|
}
|
|
30
|
-
if (
|
|
31
|
-
await fsAsync.
|
|
35
|
+
if (replace) {
|
|
36
|
+
if ((await fsAsync.stat(dest).catch(() => null))?.isDirectory()) {
|
|
37
|
+
await fsAsync.rename(dest, `${scratch}.old`);
|
|
38
|
+
}
|
|
39
|
+
await fsAsync.rename(result, dest);
|
|
40
|
+
} else {
|
|
41
|
+
if (!await fileExists(dest)) {
|
|
42
|
+
await fsAsync.rename(result, dest).catch((e) => {
|
|
43
|
+
if (e?.code != "ENOTEMPTY") throw e;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
32
46
|
}
|
|
33
|
-
await fsAsync.
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
if (
|
|
37
|
-
await fsAsync.rm(
|
|
38
|
-
await fsAsync.rm(tmpDir, { recursive: true, force: true });
|
|
39
|
-
} else if (!opts.preserveTmpDir) {
|
|
40
|
-
await fsAsync.rm(createdParentDir ?? tmpDir, { recursive: true, force: true });
|
|
47
|
+
await fsAsync.rm(scratch, { recursive: true, force: true });
|
|
48
|
+
await fsAsync.rm(`${scratch}.old`, { recursive: true, force: true });
|
|
49
|
+
} catch (e) {
|
|
50
|
+
if (!preserveTmpDir) {
|
|
51
|
+
await fsAsync.rm(scratch, { recursive: true, force: true });
|
|
41
52
|
}
|
|
53
|
+
throw e;
|
|
42
54
|
}
|
|
43
55
|
}
|
|
44
56
|
async function linkOrCp(src, dest) {
|
|
@@ -116,8 +128,29 @@ import fsAsync2 from "fs/promises";
|
|
|
116
128
|
import readlineSync from "readline-sync";
|
|
117
129
|
import dotenv from "dotenv";
|
|
118
130
|
import path2 from "path";
|
|
119
|
-
import { Octokit } from "octokit";
|
|
120
131
|
import { env } from "process";
|
|
132
|
+
function parseLinkHeader(linkHeader) {
|
|
133
|
+
function parseLinkData(linkData) {
|
|
134
|
+
return Object.fromEntries(
|
|
135
|
+
linkData.split(";").flatMap((x) => {
|
|
136
|
+
const partMatch = x.trim().match(/^([^=]+?)\s*=\s*"?([^"]+)"?$/);
|
|
137
|
+
return partMatch ? [[partMatch[1], partMatch[2]]] : [];
|
|
138
|
+
})
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
const linkDatas = linkHeader.split(/,\s*(?=<)/).flatMap((link) => {
|
|
142
|
+
const linkMatch = link.trim().match(/^<([^>]*)>(.*)$/);
|
|
143
|
+
if (linkMatch) {
|
|
144
|
+
return [{
|
|
145
|
+
url: linkMatch[1],
|
|
146
|
+
...parseLinkData(linkMatch[2])
|
|
147
|
+
}];
|
|
148
|
+
} else {
|
|
149
|
+
return [];
|
|
150
|
+
}
|
|
151
|
+
}).filter((l) => l.rel);
|
|
152
|
+
return Object.fromEntries(linkDatas.map((l) => [l.rel, l]));
|
|
153
|
+
}
|
|
121
154
|
function createURL(url, base, params = {}) {
|
|
122
155
|
const cleanParams = _2(params).pickBy((x) => x !== void 0).mapValues((v) => String(v)).value();
|
|
123
156
|
const urlObj = new URL(url, base);
|
|
@@ -127,37 +160,59 @@ function createURL(url, base, params = {}) {
|
|
|
127
160
|
}
|
|
128
161
|
return urlObj.toString();
|
|
129
162
|
}
|
|
130
|
-
function
|
|
131
|
-
|
|
163
|
+
async function fetchGitHubAPI(url, params = {}) {
|
|
164
|
+
url = createURL(url, "https://api.github.com", params);
|
|
165
|
+
const token = env.GITHUB_TOKEN;
|
|
166
|
+
const headers = token ? { Authorization: "Bearer " + token } : {};
|
|
167
|
+
const response = await fetch(url, { headers });
|
|
168
|
+
if (!response.ok) {
|
|
169
|
+
throw new Error(`GitHub API error: ${await response.text()}`);
|
|
170
|
+
}
|
|
171
|
+
return response;
|
|
172
|
+
}
|
|
173
|
+
async function fetchGitHubAPIPaginated(url, params = {}) {
|
|
174
|
+
const results = [];
|
|
175
|
+
let next = createURL(url, "https://api.github.com", { per_page: 100, ...params });
|
|
176
|
+
while (next) {
|
|
177
|
+
const response = await fetchGitHubAPI(next);
|
|
178
|
+
results.push(...await response.json());
|
|
179
|
+
next = parseLinkHeader(response.headers.get("link") ?? "").next?.url;
|
|
180
|
+
}
|
|
181
|
+
return results;
|
|
132
182
|
}
|
|
133
183
|
async function obsidianApiLogin(opts) {
|
|
134
184
|
const { interactive = false, savePath } = opts;
|
|
135
|
-
|
|
136
|
-
let email = env.OBSIDIAN_EMAIL;
|
|
137
|
-
let password = env.OBSIDIAN_PASSWORD;
|
|
185
|
+
const cached = savePath ? dotenv.parse(await fsAsync2.readFile(savePath).catch(() => "")) : {};
|
|
186
|
+
let email = env.OBSIDIAN_EMAIL ?? cached.OBSIDIAN_EMAIL;
|
|
187
|
+
let password = env.OBSIDIAN_PASSWORD ?? cached.OBSIDIAN_PASSWORD;
|
|
188
|
+
let promptedCredentials = false;
|
|
138
189
|
if (!email || !password) {
|
|
139
190
|
if (interactive) {
|
|
140
191
|
console.log("Obsidian Insiders account is required to download Obsidian beta versions.");
|
|
141
192
|
email = email || readlineSync.question("Obsidian email: ");
|
|
142
193
|
password = password || readlineSync.question("Obsidian password: ", { hideEchoBack: true });
|
|
194
|
+
promptedCredentials = true;
|
|
143
195
|
} else {
|
|
144
196
|
throw Error(
|
|
145
197
|
"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>`"
|
|
146
198
|
);
|
|
147
199
|
}
|
|
148
200
|
}
|
|
201
|
+
function parseSignin(r) {
|
|
202
|
+
return { token: r.token ? "token" : void 0, error: r.error?.toString(), license: r.license };
|
|
203
|
+
}
|
|
149
204
|
let needsMfa = false;
|
|
150
205
|
let retries = 0;
|
|
151
206
|
let signin = void 0;
|
|
152
207
|
while (!signin?.token && retries < 3) {
|
|
153
208
|
if (retries > 0 || env.CI) {
|
|
154
|
-
await sleep(2 * Math.random() + retries * retries *
|
|
209
|
+
await sleep(2 * Math.random() + retries * retries * 3);
|
|
155
210
|
}
|
|
156
211
|
let mfa = "";
|
|
157
212
|
if (needsMfa && interactive) {
|
|
158
213
|
mfa = readlineSync.question("Obsidian 2FA: ");
|
|
159
214
|
}
|
|
160
|
-
|
|
215
|
+
const response = await fetch("https://api.obsidian.md/user/signin", {
|
|
161
216
|
method: "post",
|
|
162
217
|
headers: {
|
|
163
218
|
"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",
|
|
@@ -166,6 +221,7 @@ async function obsidianApiLogin(opts) {
|
|
|
166
221
|
},
|
|
167
222
|
body: JSON.stringify({ email, password, mfa })
|
|
168
223
|
}).then((r) => r.json());
|
|
224
|
+
signin = parseSignin(response);
|
|
169
225
|
const error = signin.error?.toLowerCase();
|
|
170
226
|
if (error?.includes("2fa") && !needsMfa) {
|
|
171
227
|
needsMfa = true;
|
|
@@ -176,6 +232,7 @@ async function obsidianApiLogin(opts) {
|
|
|
176
232
|
}
|
|
177
233
|
} else if (["please wait", "try again"].some((m) => error?.includes(m))) {
|
|
178
234
|
console.warn(`Obsidian login failed: ${signin.error}`);
|
|
235
|
+
console.warn("Retrying obsidian login...");
|
|
179
236
|
retries++;
|
|
180
237
|
} else if (!signin.token) {
|
|
181
238
|
throw Error(`Obsidian login failed: ${signin.error ?? "unknown error"}`);
|
|
@@ -186,7 +243,7 @@ async function obsidianApiLogin(opts) {
|
|
|
186
243
|
} else if (!signin?.license) {
|
|
187
244
|
throw Error("Obsidian Insiders account is required to download Obsidian beta versions");
|
|
188
245
|
}
|
|
189
|
-
if (
|
|
246
|
+
if (savePath && promptedCredentials) {
|
|
190
247
|
const save = readlineSync.question("Cache credentails to disk? [y/n]: ");
|
|
191
248
|
if (["y", "yes"].includes(save.toLowerCase())) {
|
|
192
249
|
await fsAsync2.writeFile(
|
|
@@ -201,6 +258,9 @@ OBSIDIAN_PASSWORD='${password}'
|
|
|
201
258
|
return signin.token;
|
|
202
259
|
}
|
|
203
260
|
async function fetchObsidianApi(url, opts) {
|
|
261
|
+
if (!opts.token) {
|
|
262
|
+
throw Error("Obsidian credentials required to download Obsidian beta release");
|
|
263
|
+
}
|
|
204
264
|
url = createURL(url, "https://releases.obsidian.md");
|
|
205
265
|
const response = await fetch(url, {
|
|
206
266
|
headers: {
|
|
@@ -332,16 +392,16 @@ ${stderr}`);
|
|
|
332
392
|
return result;
|
|
333
393
|
}
|
|
334
394
|
async function extractObsidianAppImage(appImage, dest) {
|
|
335
|
-
await atomicCreate(dest, async (
|
|
336
|
-
await sevenZ(["x", "-o.", path4.relative(
|
|
337
|
-
return
|
|
395
|
+
await atomicCreate(dest, async (scratch) => {
|
|
396
|
+
await sevenZ(["x", "-o.", path4.relative(scratch, appImage)], { cwd: scratch });
|
|
397
|
+
return scratch;
|
|
338
398
|
});
|
|
339
399
|
}
|
|
340
400
|
async function extractObsidianTar(tar, dest) {
|
|
341
|
-
await atomicCreate(dest, async (
|
|
342
|
-
await extractGz(tar, path4.join(
|
|
343
|
-
await sevenZ(["x", "-o.", "inflated.tar"], { cwd:
|
|
344
|
-
return (await fsAsync3.readdir(
|
|
401
|
+
await atomicCreate(dest, async (scratch) => {
|
|
402
|
+
await extractGz(tar, path4.join(scratch, "inflated.tar"));
|
|
403
|
+
await sevenZ(["x", "-o.", "inflated.tar"], { cwd: scratch });
|
|
404
|
+
return (await fsAsync3.readdir(scratch)).find((p) => p.match("obsidian-"));
|
|
345
405
|
});
|
|
346
406
|
}
|
|
347
407
|
async function extractObsidianExe(exe, arch, dest) {
|
|
@@ -355,17 +415,17 @@ async function extractObsidianExe(exe, arch, dest) {
|
|
|
355
415
|
} else {
|
|
356
416
|
throw Error(`No Obsidian installer found for ${process.platform} ${process.arch}`);
|
|
357
417
|
}
|
|
358
|
-
await atomicCreate(dest, async (
|
|
359
|
-
await sevenZ(["x", "-oinstaller", path4.relative(
|
|
360
|
-
await sevenZ(["x", "-oobsidian", path4.join("installer", subArchive)], { cwd:
|
|
418
|
+
await atomicCreate(dest, async (scratch) => {
|
|
419
|
+
await sevenZ(["x", "-oinstaller", path4.relative(scratch, exe), subArchive], { cwd: scratch });
|
|
420
|
+
await sevenZ(["x", "-oobsidian", path4.join("installer", subArchive)], { cwd: scratch });
|
|
361
421
|
return "obsidian";
|
|
362
422
|
});
|
|
363
423
|
}
|
|
364
424
|
async function extractObsidianDmg(dmg, dest) {
|
|
365
425
|
dest = path4.resolve(dest);
|
|
366
|
-
await atomicCreate(dest, async (
|
|
367
|
-
await sevenZ(["x", "-o.", path4.relative(
|
|
368
|
-
const files = await fsAsync3.readdir(
|
|
426
|
+
await atomicCreate(dest, async (scratch) => {
|
|
427
|
+
await sevenZ(["x", "-o.", path4.relative(scratch, dmg), "*/Obsidian.app", "Obsidian.app"], { cwd: scratch });
|
|
428
|
+
const files = await fsAsync3.readdir(scratch);
|
|
369
429
|
if (files.includes("Obsidian.app")) {
|
|
370
430
|
return "Obsidian.app";
|
|
371
431
|
} else {
|
|
@@ -375,13 +435,9 @@ async function extractObsidianDmg(dmg, dest) {
|
|
|
375
435
|
}
|
|
376
436
|
async function fetchObsidianDesktopReleases(sinceDate, sinceSha) {
|
|
377
437
|
const repo = "obsidianmd/obsidian-releases";
|
|
378
|
-
|
|
379
|
-
let commitHistory = await github.paginate(github.rest.repos.listCommits, {
|
|
380
|
-
owner: "obsidianmd",
|
|
381
|
-
repo: "obsidian-releases",
|
|
438
|
+
let commitHistory = await fetchGitHubAPIPaginated(`repos/${repo}/commits`, {
|
|
382
439
|
path: "desktop-releases.json",
|
|
383
|
-
since: sinceDate
|
|
384
|
-
per_page: 100
|
|
440
|
+
since: sinceDate
|
|
385
441
|
});
|
|
386
442
|
commitHistory.reverse();
|
|
387
443
|
if (sinceSha) {
|
|
@@ -392,19 +448,13 @@ async function fetchObsidianDesktopReleases(sinceDate, sinceSha) {
|
|
|
392
448
|
commitHistory,
|
|
393
449
|
(commit) => fetch(`https://raw.githubusercontent.com/${repo}/${commit.sha}/desktop-releases.json`).then((r) => r.json())
|
|
394
450
|
);
|
|
395
|
-
const commitDate = commitHistory.at(-1)?.commit.committer
|
|
451
|
+
const commitDate = commitHistory.at(-1)?.commit.committer.date ?? sinceDate;
|
|
396
452
|
const commitSha = commitHistory.at(-1)?.sha ?? sinceSha;
|
|
397
453
|
return [fileHistory, { commitDate, commitSha }];
|
|
398
454
|
}
|
|
399
455
|
async function fetchObsidianGitHubReleases() {
|
|
400
|
-
const
|
|
401
|
-
|
|
402
|
-
owner: "obsidianmd",
|
|
403
|
-
repo: "obsidian-releases",
|
|
404
|
-
per_page: 100
|
|
405
|
-
});
|
|
406
|
-
gitHubReleases = gitHubReleases.reverse();
|
|
407
|
-
return gitHubReleases;
|
|
456
|
+
const gitHubReleases = await fetchGitHubAPIPaginated(`repos/obsidianmd/obsidian-releases/releases`);
|
|
457
|
+
return gitHubReleases.reverse();
|
|
408
458
|
}
|
|
409
459
|
var BROKEN_ASSETS = [
|
|
410
460
|
"https://releases.obsidian.md/release/obsidian-0.12.16.asar.gz",
|
|
@@ -518,7 +568,11 @@ function updateObsidianVersionList(args) {
|
|
|
518
568
|
minInstallerVersion = version;
|
|
519
569
|
}
|
|
520
570
|
}
|
|
521
|
-
newVersions[version] = _3.merge(
|
|
571
|
+
newVersions[version] = _3.merge(newVersions[version], {
|
|
572
|
+
minInstallerVersion: newVersions[version]?.minInstallerVersion ?? minInstallerVersion,
|
|
573
|
+
maxInstallerVersion
|
|
574
|
+
// override maxInstallerVersion if it was already set
|
|
575
|
+
});
|
|
522
576
|
}
|
|
523
577
|
for (const installerInfo of installerInfos) {
|
|
524
578
|
newVersions[installerInfo.version] = _3.merge(newVersions[installerInfo.version] ?? {}, {
|
|
@@ -677,10 +731,10 @@ var ObsidianLauncher = class {
|
|
|
677
731
|
return d;
|
|
678
732
|
}));
|
|
679
733
|
if (response.success) {
|
|
680
|
-
await atomicCreate(dest, async (
|
|
681
|
-
await fsAsync4.writeFile(path5.join(
|
|
682
|
-
return path5.join(
|
|
683
|
-
});
|
|
734
|
+
await atomicCreate(dest, async (scratch) => {
|
|
735
|
+
await fsAsync4.writeFile(path5.join(scratch, "download.json"), response.result);
|
|
736
|
+
return path5.join(scratch, "download.json");
|
|
737
|
+
}, { replace: true });
|
|
684
738
|
data = JSON.parse(response.result);
|
|
685
739
|
} else {
|
|
686
740
|
error = response.error;
|
|
@@ -747,7 +801,7 @@ var ObsidianLauncher = class {
|
|
|
747
801
|
* Resolves Obsidian app and installer version strings to absolute versions.
|
|
748
802
|
* @param appVersion specific version or one of
|
|
749
803
|
* - "latest": Get the current latest non-beta Obsidian version
|
|
750
|
-
* - "latest-beta": Get the current latest beta Obsidian version (or latest
|
|
804
|
+
* - "latest-beta": Get the current latest beta Obsidian version (or latest if there is no current beta)
|
|
751
805
|
* - "earliest": Get the `minAppVersion` set in your `manifest.json`
|
|
752
806
|
* @param installerVersion specific version or one of
|
|
753
807
|
* - "latest": Get the latest Obsidian installer compatible with `appVersion`
|
|
@@ -881,31 +935,29 @@ var ObsidianLauncher = class {
|
|
|
881
935
|
const versionInfo = await this.getVersionInfo(installerVersion);
|
|
882
936
|
installerVersion = versionInfo.version;
|
|
883
937
|
const installerInfo = await this.getInstallerInfo(installerVersion, { platform, arch });
|
|
884
|
-
const
|
|
938
|
+
const installerDir = path5.join(this.cacheDir, `obsidian-installer/${platform}-${arch}/Obsidian-${installerVersion}`);
|
|
885
939
|
let binaryPath;
|
|
886
940
|
let extractor;
|
|
887
941
|
if (platform == "linux") {
|
|
888
|
-
binaryPath = path5.join(
|
|
942
|
+
binaryPath = path5.join(installerDir, "obsidian");
|
|
889
943
|
extractor = (installer, dest) => extractObsidianAppImage(installer, dest);
|
|
890
944
|
} else if (platform == "win32") {
|
|
891
|
-
binaryPath = path5.join(
|
|
945
|
+
binaryPath = path5.join(installerDir, "Obsidian.exe");
|
|
892
946
|
extractor = (installer, dest) => extractObsidianExe(installer, arch, dest);
|
|
893
947
|
} else if (platform == "darwin") {
|
|
894
|
-
binaryPath = path5.join(
|
|
948
|
+
binaryPath = path5.join(installerDir, "Contents/MacOS/Obsidian");
|
|
895
949
|
extractor = (installer, dest) => extractObsidianDmg(installer, dest);
|
|
896
950
|
} else {
|
|
897
951
|
throw Error(`Unsupported platform ${platform}`);
|
|
898
952
|
}
|
|
899
|
-
|
|
953
|
+
await atomicCreate(installerDir, async (scratch) => {
|
|
900
954
|
console.log(`Downloading Obsidian installer v${installerVersion}...`);
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
});
|
|
908
|
-
}
|
|
955
|
+
const installer = path5.join(scratch, "installer");
|
|
956
|
+
await downloadResponse(await fetch(installerInfo.url), installer);
|
|
957
|
+
const extracted = path5.join(scratch, "extracted");
|
|
958
|
+
await extractor(installer, extracted);
|
|
959
|
+
return extracted;
|
|
960
|
+
}, { replace: false });
|
|
909
961
|
return binaryPath;
|
|
910
962
|
}
|
|
911
963
|
/**
|
|
@@ -924,29 +976,27 @@ var ObsidianLauncher = class {
|
|
|
924
976
|
throw Error(`No asar found for Obsidian version ${appVersion}`);
|
|
925
977
|
}
|
|
926
978
|
const appPath = path5.join(this.cacheDir, "obsidian-app", `obsidian-${versionInfo.version}.asar`);
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
if (isInsiders) {
|
|
933
|
-
if (!this.obsidianApiToken) {
|
|
934
|
-
this.obsidianApiToken = await obsidianApiLogin({
|
|
935
|
-
interactive: this.interactive,
|
|
936
|
-
savePath: path5.join(this.cacheDir, "obsidian-credentials.env")
|
|
937
|
-
});
|
|
938
|
-
}
|
|
939
|
-
response = await fetchObsidianApi(appUrl, { token: this.obsidianApiToken });
|
|
940
|
-
} else {
|
|
941
|
-
response = await fetch(appUrl);
|
|
942
|
-
}
|
|
943
|
-
const archive = path5.join(tmpDir, "app.asar.gz");
|
|
944
|
-
const asar = path5.join(tmpDir, "app.asar");
|
|
945
|
-
await downloadResponse(response, archive);
|
|
946
|
-
await extractGz(archive, asar);
|
|
947
|
-
return asar;
|
|
979
|
+
const isInsiders = new URL(appUrl).hostname.endsWith(".obsidian.md");
|
|
980
|
+
if (isInsiders && !this.obsidianApiToken && !await fileExists(appPath)) {
|
|
981
|
+
this.obsidianApiToken = await obsidianApiLogin({
|
|
982
|
+
interactive: this.interactive,
|
|
983
|
+
savePath: path5.join(this.cacheDir, "obsidian-credentials.env")
|
|
948
984
|
});
|
|
949
985
|
}
|
|
986
|
+
await atomicCreate(appPath, async (scratch) => {
|
|
987
|
+
console.log(`Downloading Obsidian app v${versionInfo.version} ...`);
|
|
988
|
+
let response;
|
|
989
|
+
if (isInsiders) {
|
|
990
|
+
response = await fetchObsidianApi(appUrl, { token: this.obsidianApiToken });
|
|
991
|
+
} else {
|
|
992
|
+
response = await fetch(appUrl);
|
|
993
|
+
}
|
|
994
|
+
const archive = path5.join(scratch, "app.asar.gz");
|
|
995
|
+
const asar = path5.join(scratch, "app.asar");
|
|
996
|
+
await downloadResponse(response, archive);
|
|
997
|
+
await extractGz(archive, asar);
|
|
998
|
+
return asar;
|
|
999
|
+
}, { replace: false });
|
|
950
1000
|
return appPath;
|
|
951
1001
|
}
|
|
952
1002
|
/**
|
|
@@ -963,26 +1013,24 @@ var ObsidianLauncher = class {
|
|
|
963
1013
|
async downloadChromedriver(installerVersion, opts = {}) {
|
|
964
1014
|
const { platform, arch } = _4.defaults({}, opts, currentPlatform);
|
|
965
1015
|
const installerInfo = await this.getInstallerInfo(installerVersion, { platform, arch });
|
|
966
|
-
const
|
|
1016
|
+
const chromedriverDir = path5.join(this.cacheDir, `electron-chromedriver/${platform}-${arch}/${installerInfo.electron}`);
|
|
967
1017
|
let chromedriverPath;
|
|
968
1018
|
if (process.platform == "win32") {
|
|
969
|
-
chromedriverPath = path5.join(
|
|
1019
|
+
chromedriverPath = path5.join(chromedriverDir, `chromedriver.exe`);
|
|
970
1020
|
} else {
|
|
971
|
-
chromedriverPath = path5.join(
|
|
1021
|
+
chromedriverPath = path5.join(chromedriverDir, `chromedriver`);
|
|
972
1022
|
}
|
|
973
|
-
|
|
1023
|
+
await atomicCreate(chromedriverDir, async (scratch) => {
|
|
974
1024
|
console.log(`Downloading chromedriver for electron ${installerInfo.electron} ...`);
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
cacheRoot: path5.join(tmpDir, "download")
|
|
980
|
-
});
|
|
981
|
-
const extracted = path5.join(tmpDir, "extracted");
|
|
982
|
-
await extractZip(chromedriverZipPath, { dir: extracted });
|
|
983
|
-
return extracted;
|
|
1025
|
+
const chromedriverZipPath = await downloadArtifact({
|
|
1026
|
+
version: installerInfo.electron,
|
|
1027
|
+
artifactName: "chromedriver",
|
|
1028
|
+
cacheRoot: path5.join(scratch, "download")
|
|
984
1029
|
});
|
|
985
|
-
|
|
1030
|
+
const extracted = path5.join(scratch, "extracted");
|
|
1031
|
+
await extractZip(chromedriverZipPath, { dir: extracted });
|
|
1032
|
+
return extracted;
|
|
1033
|
+
}, { replace: false });
|
|
986
1034
|
return chromedriverPath;
|
|
987
1035
|
}
|
|
988
1036
|
/**
|
|
@@ -997,14 +1045,12 @@ var ObsidianLauncher = class {
|
|
|
997
1045
|
);
|
|
998
1046
|
}
|
|
999
1047
|
const apkPath = path5.join(this.cacheDir, "obsidian-apk", `obsidian-${versionInfo.version}.apk`);
|
|
1000
|
-
|
|
1048
|
+
await atomicCreate(apkPath, async (scratch) => {
|
|
1001
1049
|
console.log(`Downloading Obsidian apk v${versionInfo.version} ...`);
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
});
|
|
1007
|
-
}
|
|
1050
|
+
const dest = path5.join(scratch, "obsidian.apk");
|
|
1051
|
+
await downloadResponse(await fetch(apkUrl), dest);
|
|
1052
|
+
return dest;
|
|
1053
|
+
}, { replace: false });
|
|
1008
1054
|
return apkPath;
|
|
1009
1055
|
}
|
|
1010
1056
|
/** Gets the latest version of a plugin. */
|
|
@@ -1031,23 +1077,21 @@ var ObsidianLauncher = class {
|
|
|
1031
1077
|
}
|
|
1032
1078
|
version = semver2.valid(version);
|
|
1033
1079
|
const pluginDir = path5.join(this.cacheDir, "obsidian-plugins", repo, version);
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
}
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
});
|
|
1050
|
-
}
|
|
1080
|
+
await atomicCreate(pluginDir, async (scratch) => {
|
|
1081
|
+
const assetsToDownload = { "manifest.json": true, "main.js": true, "styles.css": false };
|
|
1082
|
+
await Promise.all(
|
|
1083
|
+
Object.entries(assetsToDownload).map(async ([file, required]) => {
|
|
1084
|
+
const url = `https://github.com/${repo}/releases/download/${version}/${file}`;
|
|
1085
|
+
const response = await fetch(url);
|
|
1086
|
+
if (response.ok) {
|
|
1087
|
+
await downloadResponse(response, path5.join(scratch, file));
|
|
1088
|
+
} else if (required) {
|
|
1089
|
+
throw Error(`No ${file} found for ${repo} version ${version}`);
|
|
1090
|
+
}
|
|
1091
|
+
})
|
|
1092
|
+
);
|
|
1093
|
+
return scratch;
|
|
1094
|
+
}, { replace: false });
|
|
1051
1095
|
return pluginDir;
|
|
1052
1096
|
}
|
|
1053
1097
|
/**
|
|
@@ -1199,31 +1243,29 @@ var ObsidianLauncher = class {
|
|
|
1199
1243
|
}
|
|
1200
1244
|
version = semver2.valid(version);
|
|
1201
1245
|
const themeDir = path5.join(this.cacheDir, "obsidian-themes", repo, version);
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
if (
|
|
1207
|
-
|
|
1208
|
-
throw Error(`No theme version "${version}" found`);
|
|
1209
|
-
}
|
|
1210
|
-
baseUrl = `https://raw.githubusercontent.com/${repo}/HEAD`;
|
|
1246
|
+
await atomicCreate(themeDir, async (scratch) => {
|
|
1247
|
+
const assetsToDownload = ["manifest.json", "theme.css"];
|
|
1248
|
+
let baseUrl = `https://github.com/${repo}/releases/download/${version}`;
|
|
1249
|
+
if (!(await fetch(`${baseUrl}/manifest.json`)).ok) {
|
|
1250
|
+
if (version != latest) {
|
|
1251
|
+
throw Error(`No theme version "${version}" found`);
|
|
1211
1252
|
}
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1253
|
+
baseUrl = `https://raw.githubusercontent.com/${repo}/HEAD`;
|
|
1254
|
+
}
|
|
1255
|
+
await Promise.all(
|
|
1256
|
+
assetsToDownload.map(
|
|
1257
|
+
async (file) => {
|
|
1258
|
+
const url = `${baseUrl}/${file}`;
|
|
1259
|
+
const response = await fetch(url);
|
|
1260
|
+
if (response.ok) {
|
|
1261
|
+
await downloadResponse(response, path5.join(scratch, file));
|
|
1262
|
+
} else {
|
|
1263
|
+
throw Error(`No ${file} found for ${repo}`);
|
|
1222
1264
|
}
|
|
1223
|
-
|
|
1224
|
-
)
|
|
1225
|
-
|
|
1226
|
-
}
|
|
1265
|
+
}
|
|
1266
|
+
)
|
|
1267
|
+
);
|
|
1268
|
+
}, { replace: false });
|
|
1227
1269
|
return themeDir;
|
|
1228
1270
|
}
|
|
1229
1271
|
/**
|
|
@@ -1541,4 +1583,4 @@ export {
|
|
|
1541
1583
|
watchFiles,
|
|
1542
1584
|
ObsidianLauncher
|
|
1543
1585
|
};
|
|
1544
|
-
//# sourceMappingURL=chunk-
|
|
1586
|
+
//# sourceMappingURL=chunk-HMKNUWAY.js.map
|