open source is social v-it.org
at main 83 lines 2.9 kB view raw
1// SPDX-License-Identifier: MIT 2// Copyright (c) 2026 sol pbc 3 4import { execFileSync } from 'node:child_process'; 5import { existsSync, readFileSync, writeFileSync } from 'node:fs'; 6import { join, resolve } from 'node:path'; 7import { which } from '../lib/compat.js'; 8import { mark, name } from '../lib/brand.js'; 9 10export default function register(program) { 11 program 12 .command('hack') 13 .description('Fork and install vit from source') 14 .option('--from <repo>', 'Clone an existing fork instead of creating a new one (e.g. user/vit)') 15 .action(async (opts) => { 16 try { 17 const ghPath = which('gh'); 18 if (!opts.from && !ghPath) { 19 console.error(`${name} hack requires gh (GitHub CLI). Install it from https://cli.github.com`); 20 process.exitCode = 1; 21 return; 22 } 23 24 const gitPath = which('git'); 25 if (opts.from && !gitPath) { 26 console.error('missing required tool: git'); 27 process.exitCode = 1; 28 return; 29 } 30 31 const repo = opts.from || 'solpbc/vit'; 32 const dirName = repo.split('/').pop(); 33 const dirPath = resolve(process.cwd(), dirName); 34 const cloned = !existsSync(dirPath); 35 36 if (!cloned) { 37 console.log(`${mark} ${dirName}/ already exists, skipping clone`); 38 } else if (opts.from) { 39 execFileSync('git', ['clone', 'https://github.com/' + opts.from + '.git', dirName], { stdio: 'inherit' }); 40 } else { 41 execFileSync('gh', ['repo', 'fork', 'solpbc/vit', '--clone'], { stdio: 'inherit' }); 42 } 43 44 process.chdir(dirName); 45 46 const bunPath = which('bun'); 47 if (!bunPath) { 48 console.error('missing required tool: bun'); 49 process.exitCode = 1; 50 return; 51 } 52 53 execFileSync('bun', ['install'], { stdio: 'inherit' }); 54 execFileSync('node', [join(process.cwd(), 'bin', 'vit.js'), 'link'], { stdio: 'inherit' }); 55 56 if (!opts.from) { 57 const remote = execFileSync( 58 'gh', 59 ['repo', 'view', '--json', 'nameWithOwner', '-q', '.nameWithOwner'], 60 { encoding: 'utf-8' } 61 ).trim(); 62 const hackPath = join(process.cwd(), 'hack'); 63 if (existsSync(hackPath)) { 64 const current = readFileSync(hackPath, 'utf-8'); 65 writeFileSync(hackPath, current.replace('SELF="solpbc/vit"', `SELF="${remote}"`)); 66 } 67 } 68 69 if (opts.from && cloned) { 70 try { 71 execFileSync('git', ['remote', 'add', 'upstream', 'https://github.com/solpbc/vit.git'], { stdio: 'inherit' }); 72 } catch {} 73 } 74 75 console.log(''); 76 console.log(`${mark} ${name} installed from source`); 77 console.log(`run: cd ${dirName}`); 78 } catch (err) { 79 console.error(err instanceof Error ? err.message : String(err)); 80 process.exitCode = 1; 81 } 82 }); 83}