buddymac 0.1.3 → 0.1.5
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 +2 -0
- package/cli.mjs +21 -10
- package/package.json +12 -4
- package/release.json +4 -3
package/README.md
CHANGED
|
@@ -17,3 +17,5 @@ npx buddymac --help
|
|
|
17
17
|
The app is signed and notarized by Apple, with the notarization ticket included. The installer preserves macOS download protection.
|
|
18
18
|
|
|
19
19
|
Source and downloads: https://github.com/OxFrancesco/BuddyMac
|
|
20
|
+
|
|
21
|
+
The installer downloads the notarized app using macOS curl with HTTP/2 and a smaller tar.xz archive. The installed app remains in Applications after Terminal closes.
|
package/cli.mjs
CHANGED
|
@@ -4,11 +4,12 @@ import { createWriteStream } from 'node:fs';
|
|
|
4
4
|
import { access, mkdir, mkdtemp, readFile, rename, rm } from 'node:fs/promises';
|
|
5
5
|
import { homedir } from 'node:os';
|
|
6
6
|
import { join, resolve } from 'node:path';
|
|
7
|
-
import { spawnSync } from 'node:child_process';
|
|
8
|
-
import {
|
|
7
|
+
import { spawn, spawnSync } from 'node:child_process';
|
|
8
|
+
import { Transform } from 'node:stream';
|
|
9
9
|
import { pipeline } from 'node:stream/promises';
|
|
10
10
|
|
|
11
11
|
const release = JSON.parse(await readFile(new URL('./release.json', import.meta.url), 'utf8'));
|
|
12
|
+
const { version: installerVersion } = JSON.parse(await readFile(new URL('./package.json', import.meta.url), 'utf8'));
|
|
12
13
|
const args = process.argv.slice(2);
|
|
13
14
|
const help = `Usage: npx buddymac [--destination <folder>] [--no-open]
|
|
14
15
|
|
|
@@ -19,7 +20,7 @@ The download is signed and notarized by Apple. macOS download protection stays e
|
|
|
19
20
|
|
|
20
21
|
--destination <folder> Install in a different folder
|
|
21
22
|
--no-open Install without opening the app
|
|
22
|
-
--version Print the
|
|
23
|
+
--version Print the installer version
|
|
23
24
|
--help Show this help
|
|
24
25
|
`;
|
|
25
26
|
|
|
@@ -37,7 +38,7 @@ async function install() {
|
|
|
37
38
|
for (let i = 0; i < args.length; i++) {
|
|
38
39
|
switch (args[i]) {
|
|
39
40
|
case '--help': case '-h': process.stdout.write(help); return;
|
|
40
|
-
case '--version': process.stdout.write(`${
|
|
41
|
+
case '--version': process.stdout.write(`${installerVersion}\n`); return;
|
|
41
42
|
case '--no-open': open = false; break;
|
|
42
43
|
case '--destination':
|
|
43
44
|
if (!args[i + 1] || args[i + 1].startsWith('--')) throw new Error('--destination requires a folder.');
|
|
@@ -65,12 +66,20 @@ async function install() {
|
|
|
65
66
|
if (error.code !== 'ENOENT') throw error;
|
|
66
67
|
}
|
|
67
68
|
stage = await mkdtemp(join(destination, '.buddymac-'));
|
|
68
|
-
const archive = join(stage, 'BuddyMac.
|
|
69
|
+
const archive = join(stage, 'BuddyMac.tar.xz');
|
|
69
70
|
process.stdout.write(`Downloading BuddyMac ${release.version}…\n`);
|
|
70
71
|
const downloadStarted = performance.now();
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
const download = spawn('/usr/bin/curl', [
|
|
73
|
+
'--disable', '--fail', '--location', '--http2', '--proto', '=https', '--proto-redir', '=https',
|
|
74
|
+
'--silent', '--show-error', '--connect-timeout', '20', '--max-time', '300', release.url,
|
|
75
|
+
], { env: { ...process.env }, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
76
|
+
let downloadError = '';
|
|
77
|
+
download.stderr.on('data', chunk => { downloadError = (downloadError + chunk.toString()).slice(-4096); });
|
|
78
|
+
const finished = new Promise((resolve, reject) => {
|
|
79
|
+
download.once('error', reject);
|
|
80
|
+
download.once('close', code => code === 0 ? resolve() : reject(new Error(downloadError.trim() || `Download failed: curl exited with ${code}.`)));
|
|
81
|
+
});
|
|
82
|
+
const total = release.bytes;
|
|
74
83
|
let received = 0;
|
|
75
84
|
const hash = createHash('sha256');
|
|
76
85
|
const meter = new Transform({ transform(chunk, encoding, done) {
|
|
@@ -87,15 +96,17 @@ async function install() {
|
|
|
87
96
|
};
|
|
88
97
|
const timer = setInterval(progress, process.stdout.isTTY ? 250 : 5000);
|
|
89
98
|
try {
|
|
90
|
-
await pipeline(
|
|
99
|
+
await Promise.all([finished, pipeline(download.stdout, meter, createWriteStream(archive, { flags: 'wx' }))]);
|
|
91
100
|
} finally {
|
|
101
|
+
if (download.exitCode === null) download.kill();
|
|
102
|
+
await finished.catch(() => {});
|
|
92
103
|
clearInterval(timer);
|
|
93
104
|
if (process.stdout.isTTY) process.stdout.write('\r\x1b[2K');
|
|
94
105
|
}
|
|
95
106
|
if (hash.digest('hex') !== release.sha256) throw new Error('Download checksum mismatch. No app was installed.');
|
|
96
107
|
process.stdout.write(`Download verified in ${((performance.now() - downloadStarted) / 1000).toFixed(1)}s. Unpacking…\n`);
|
|
97
108
|
const unpackStarted = performance.now();
|
|
98
|
-
run('/usr/bin/
|
|
109
|
+
run('/usr/bin/tar', ['-xJf', archive, '-C', stage]);
|
|
99
110
|
const app = join(stage, 'BuddyMac.app');
|
|
100
111
|
process.stdout.write(`Unpacked in ${((performance.now() - unpackStarted) / 1000).toFixed(1)}s. Checking Apple signature and notarization…\n`);
|
|
101
112
|
const verificationStarted = performance.now();
|
package/package.json
CHANGED
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "buddymac",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Download and install BuddyMac for Apple Silicon Macs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"buddymac": "cli.mjs"
|
|
8
8
|
},
|
|
9
|
-
"files": [
|
|
9
|
+
"files": [
|
|
10
|
+
"cli.mjs",
|
|
11
|
+
"release.json",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
10
14
|
"engines": {
|
|
11
15
|
"node": ">=20"
|
|
12
16
|
},
|
|
13
|
-
"os": [
|
|
14
|
-
|
|
17
|
+
"os": [
|
|
18
|
+
"darwin"
|
|
19
|
+
],
|
|
20
|
+
"cpu": [
|
|
21
|
+
"arm64"
|
|
22
|
+
],
|
|
15
23
|
"repository": {
|
|
16
24
|
"type": "git",
|
|
17
25
|
"url": "git+https://github.com/OxFrancesco/BuddyMac.git",
|
package/release.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.1.
|
|
3
|
-
"url": "https://github.com/OxFrancesco/BuddyMac/releases/download/v0.1.
|
|
4
|
-
"sha256": "
|
|
2
|
+
"version": "0.1.5",
|
|
3
|
+
"url": "https://github.com/OxFrancesco/BuddyMac/releases/download/v0.1.5/BuddyMac-darwin-arm64.tar.xz",
|
|
4
|
+
"sha256": "f4eeeaee0482def2dd51e8ba868f64a23937c3b23d9f940818f4e5357816f6a9",
|
|
5
|
+
"bytes": 28083068
|
|
5
6
|
}
|