open source is social v-it.org
1// SPDX-License-Identifier: MIT
2// Copyright (c) 2026 sol pbc
3
4import { existsSync, mkdirSync, symlinkSync, unlinkSync, readlinkSync, writeFileSync } from 'node:fs';
5import { join, resolve } from 'node:path';
6import { mark, name } from '../lib/brand.js';
7
8export default function register(program) {
9 program
10 .command('link')
11 .description('Link vit binary into ~/.local/bin (or create .cmd shim on Windows)')
12 .action(async () => {
13 try {
14 const vitBin = resolve(import.meta.dirname, '..', '..', 'bin', 'vit.js');
15 if (!existsSync(vitBin)) {
16 console.error(`${name} link could not find ${vitBin}`);
17 process.exitCode = 1;
18 return;
19 }
20
21 let binDir;
22 if (process.platform === 'win32') {
23 const home = process.env.USERPROFILE || process.env.HOME;
24 binDir = join(home, '.local', 'bin');
25 mkdirSync(binDir, { recursive: true });
26 const target = join(binDir, 'vit.cmd');
27 writeFileSync(target, `@node "${vitBin}" %*\n`);
28 console.log(`${mark} link: ${target} -> ${vitBin}`);
29 } else {
30 binDir = join(process.env.HOME, '.local', 'bin');
31 mkdirSync(binDir, { recursive: true });
32 const target = join(binDir, 'vit');
33 if (existsSync(target)) {
34 try {
35 const current = readlinkSync(target);
36 if (current === vitBin) {
37 console.log(`${mark} link: already linked`);
38 } else {
39 unlinkSync(target);
40 symlinkSync(vitBin, target);
41 console.log(`${mark} link: ${target} -> ${vitBin}`);
42 }
43 } catch {
44 unlinkSync(target);
45 symlinkSync(vitBin, target);
46 console.log(`${mark} link: ${target} -> ${vitBin}`);
47 }
48 } else {
49 symlinkSync(vitBin, target);
50 console.log(`${mark} link: ${target} -> ${vitBin}`);
51 }
52 }
53
54 const pathDirs = (process.env.PATH || '').split(process.platform === 'win32' ? ';' : ':');
55 if (!pathDirs.includes(binDir)) {
56 const shell = (process.env.SHELL || '').split('/').pop();
57 let instruction = '[Environment]::SetEnvironmentVariable("PATH", "$env:USERPROFILE\\.local\\bin;" + $env:PATH, "User")';
58 if (shell === 'fish') {
59 instruction = 'set -Ua fish_user_paths ~/.local/bin';
60 } else if (shell === 'zsh') {
61 instruction = 'echo \'export PATH="$HOME/.local/bin:$PATH"\' >> ~/.zshrc';
62 } else if (shell === 'bash') {
63 instruction = 'echo \'export PATH="$HOME/.local/bin:$PATH"\' >> ~/.bashrc';
64 }
65 console.log(`${mark} note: add ~/.local/bin to your PATH:`);
66 console.log(instruction);
67 } else {
68 console.log(`${mark} PATH: ok`);
69 }
70 } catch (err) {
71 console.error(err instanceof Error ? err.message : String(err));
72 process.exitCode = 1;
73 }
74 });
75}