@jonaskahn/relo 0.2.1-beta.59.2f8fb615 → 0.2.1-beta.61.b8586e68
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/lib/install.mjs +6 -0
- package/lib/shortcut.mjs +41 -0
- package/lib/uninstall.mjs +3 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -41,6 +41,8 @@ that output under the install: npm otherwise runs it in the background and
|
|
|
41
41
|
shows nothing until the command ends, which makes a slow download look stuck.
|
|
42
42
|
|
|
43
43
|
State lives in `~/.relo` (`$RELO_HOME`), shared with every other installer.
|
|
44
|
+
On Windows the install also adds a Desktop "Relo" shortcut that restarts the
|
|
45
|
+
daemon without opening a terminal.
|
|
44
46
|
Never installed twice: if another Relo is on your PATH, this one refuses and
|
|
45
47
|
tells you where it found it.
|
|
46
48
|
|
package/lib/install.mjs
CHANGED
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
warn
|
|
43
43
|
} from './progress.mjs';
|
|
44
44
|
import { target } from './platform.mjs';
|
|
45
|
+
import { createDesktopShortcut } from './shortcut.mjs';
|
|
45
46
|
import { assets, checksumsUrl, pinnedTag, selectBundle, tagFromArgs, url } from './release.mjs';
|
|
46
47
|
import { extractBinary } from './archive.mjs';
|
|
47
48
|
|
|
@@ -211,6 +212,11 @@ try {
|
|
|
211
212
|
done(`${label('CONFLICT')} no other relo install`);
|
|
212
213
|
|
|
213
214
|
const destination = await fromRelease(tag, asset, startedAt);
|
|
215
|
+
if (createDesktopShortcut(destination)) {
|
|
216
|
+
done(`${label('SHORTCUT')} Desktop\\Relo`);
|
|
217
|
+
} else if (asset.os === 'windows') {
|
|
218
|
+
note('no Desktop shortcut was created; run: relo daemon restart --force');
|
|
219
|
+
}
|
|
214
220
|
if (startNow === 'yes') {
|
|
215
221
|
closeScreen();
|
|
216
222
|
// The daemon's error goes into the result block rather than through
|
package/lib/shortcut.mjs
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// The Desktop shortcut a Windows install leaves, the same one Relo-Setup
|
|
2
|
+
// creates: it restarts the daemon through the GUI-subsystem relo.exe, so
|
|
3
|
+
// opening it shows no terminal. Other platforms have no such shortcut.
|
|
4
|
+
import { spawnSync } from 'node:child_process';
|
|
5
|
+
|
|
6
|
+
const NAME = 'Relo.lnk';
|
|
7
|
+
|
|
8
|
+
// run executes a PowerShell script with the values passed through the
|
|
9
|
+
// environment, so a path never needs quoting.
|
|
10
|
+
function run(script, env) {
|
|
11
|
+
const result = spawnSync('powershell', ['-NoProfile', '-NonInteractive', '-Command', script], {
|
|
12
|
+
env: { ...process.env, ...env },
|
|
13
|
+
stdio: 'ignore'
|
|
14
|
+
});
|
|
15
|
+
return result.status === 0;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const DESKTOP = "$desktop = [Environment]::GetFolderPath('Desktop'); $link = Join-Path $desktop '" + NAME + "';";
|
|
19
|
+
|
|
20
|
+
// createDesktopShortcut writes the shortcut for binary and reports whether it
|
|
21
|
+
// exists afterwards. The working directory is the profile, because the
|
|
22
|
+
// install directory is not a place to write.
|
|
23
|
+
export function createDesktopShortcut(binary, { nodePlatform = process.platform } = {}) {
|
|
24
|
+
if (nodePlatform !== 'win32') return false;
|
|
25
|
+
return run(
|
|
26
|
+
DESKTOP +
|
|
27
|
+
'$s = (New-Object -ComObject WScript.Shell).CreateShortcut($link);' +
|
|
28
|
+
'$s.TargetPath = $env:RELO_BINARY;' +
|
|
29
|
+
"$s.Arguments = 'daemon restart --force';" +
|
|
30
|
+
'$s.IconLocation = $env:RELO_BINARY;' +
|
|
31
|
+
'$s.WorkingDirectory = $env:USERPROFILE;' +
|
|
32
|
+
'$s.Save()',
|
|
33
|
+
{ RELO_BINARY: binary }
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// removeDesktopShortcut deletes the shortcut; a missing one is fine.
|
|
38
|
+
export function removeDesktopShortcut({ nodePlatform = process.platform } = {}) {
|
|
39
|
+
if (nodePlatform !== 'win32') return false;
|
|
40
|
+
return run(DESKTOP + 'Remove-Item -LiteralPath $link -Force -ErrorAction SilentlyContinue', {});
|
|
41
|
+
}
|
package/lib/uninstall.mjs
CHANGED
|
@@ -15,12 +15,14 @@ import { spawnSync } from 'node:child_process';
|
|
|
15
15
|
|
|
16
16
|
import { quiesce, reloHome } from './daemon.mjs';
|
|
17
17
|
import { target } from './platform.mjs';
|
|
18
|
+
import { removeDesktopShortcut } from './shortcut.mjs';
|
|
18
19
|
|
|
19
20
|
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
20
21
|
const binary = resolve(packageRoot, 'bin', target().name);
|
|
21
22
|
const home = reloHome();
|
|
22
23
|
|
|
23
24
|
try {
|
|
25
|
+
removeDesktopShortcut();
|
|
24
26
|
if (existsSync(binary)) {
|
|
25
27
|
spawnSync(binary, ['--home', home, 'uninstall', '--prepare'], { stdio: 'inherit' });
|
|
26
28
|
} else {
|
|
@@ -28,4 +30,4 @@ try {
|
|
|
28
30
|
}
|
|
29
31
|
} catch (error) {
|
|
30
32
|
console.warn(`relo: could not stop the running daemon; ${error.message}`);
|
|
31
|
-
}
|
|
33
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jonaskahn/relo",
|
|
3
|
-
"version": "0.2.1-beta.
|
|
3
|
+
"version": "0.2.1-beta.61.b8586e68",
|
|
4
4
|
"description": "One local proxy that lets Codex, Claude Code, Cursor and Grok, etc. Talk to any model, any provider with no config changes",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"type": "module",
|
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
"lib/platform.mjs",
|
|
50
50
|
"lib/progress.mjs",
|
|
51
51
|
"lib/release.mjs",
|
|
52
|
+
"lib/shortcut.mjs",
|
|
52
53
|
"lib/uninstall.mjs",
|
|
53
54
|
"README.md"
|
|
54
55
|
],
|