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 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 { Readable, Transform } from 'node:stream';
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 bundled release version
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(`${release.version}\n`); return;
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.zip');
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 response = await fetch(release.url, { signal: AbortSignal.timeout(300_000) });
72
- if (!response.ok || !response.body) throw new Error(`Download failed: HTTP ${response.status}. ${release.url}`);
73
- const total = Number(response.headers.get('content-length'));
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(Readable.fromWeb(response.body), meter, createWriteStream(archive, { flags: 'wx' }));
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/ditto', ['-x', '-k', archive, stage]);
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",
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": ["cli.mjs", "release.json", "README.md"],
9
+ "files": [
10
+ "cli.mjs",
11
+ "release.json",
12
+ "README.md"
13
+ ],
10
14
  "engines": {
11
15
  "node": ">=20"
12
16
  },
13
- "os": ["darwin"],
14
- "cpu": ["arm64"],
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",
3
- "url": "https://github.com/OxFrancesco/BuddyMac/releases/download/v0.1.3/BuddyMac-darwin-arm64.zip",
4
- "sha256": "4a4fcd984d46ca6644eed072aae50eecf1bdbe7bdb2710e9cd10e4c54a791165"
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
  }