#!/usr/bin/env bun import { $ } from "bun" const PI_HOST = process.env.PI_HOST ?? "phone.local" const PI_DIR = process.env.PI_DIR ?? "/home/corey/phone" // Parse command line arguments const shouldBootstrap = process.argv.includes("--bootstrap") console.log(`๐Ÿงช Run basic tests...\n`) await $`bun run typecheck` console.log(`๐Ÿ“ฆ Deploying to ${PI_HOST}...\n`) // Create directory on Pi console.log("Creating directory on Pi...") await $`ssh ${PI_HOST} "mkdir -p ${PI_DIR}"` // Sync files from . directory to Pi (only transfers changed files) console.log("Syncing files from . directory...") await $`rsync -avz --delete --exclude-from='../.gitignore' --exclude='.git' . ${PI_HOST}:${PI_DIR}/` // Make all TypeScript files executable console.log("Making scripts executable...") await $`ssh ${PI_HOST} "chmod +x ${PI_DIR}/scripts/*"` console.log("\nโœ“ Files deployed!\n") // Run bootstrap if requested if (shouldBootstrap) { console.log("๐Ÿž Running bootstrap-bun on Pi...\n") await $`ssh ${PI_HOST} "bash ${PI_DIR}/scripts/bootstrap-bun.sh"` console.log("Running bootstrap on Pi...\n") await $`ssh ${PI_HOST} "cd ${PI_DIR} && sudo bun ${PI_DIR}/scripts/bootstrap.ts ${PI_DIR}"` } // make console beep await $`afplay /System/Library/Sounds/Blow.aiff` // Always check if services exist and restart them (whether we bootstrapped or not) console.log("Checking for existing services...") const apServiceExists = await $`ssh ${PI_HOST} "systemctl is-enabled phone-ap.service"` .nothrow() .quiet() const webServiceExists = await $`ssh ${PI_HOST} "systemctl is-enabled phone-web.service"` .nothrow() .quiet() if (apServiceExists.exitCode === 0 && webServiceExists.exitCode === 0) { console.log("Restarting services...") await $`ssh ${PI_HOST} "sudo systemctl restart phone-ap.service phone-web.service"` console.log("โœ“ Services restarted\n") } else if (!shouldBootstrap) { console.log("Services not installed. Run with --bootstrap to install.\n") } console.log(` โœ“ Deploy complete! Access via WiFi at http://phone.local The Pi is discoverable as "phone-setup" `)