A simple command-line tool to start NetBSD virtual machines using QEMU with sensible defaults.
at main 98 lines 2.4 kB view raw
1import { Table } from "@cliffy/table"; 2import dayjs from "dayjs"; 3import relativeTime from "dayjs/plugin/relativeTime.js"; 4import utc from "dayjs/plugin/utc.js"; 5import { Effect, pipe } from "effect"; 6import type { Volume } from "../db.ts"; 7import type { DbError } from "../mod.ts"; 8import { deleteVolume, getVolume, listVolumes } from "../volumes.ts"; 9 10dayjs.extend(relativeTime); 11dayjs.extend(utc); 12 13const createTable = () => 14 Effect.succeed( 15 new Table( 16 ["NAME", "VOLUME ID", "CREATED"], 17 ), 18 ); 19 20const populateTable = (table: Table, volumes: Volume[]) => 21 Effect.sync(() => { 22 for (const volume of volumes) { 23 table.push([ 24 volume.name, 25 volume.id, 26 dayjs.utc(volume.createdAt).local().fromNow(), 27 ]); 28 } 29 return table; 30 }); 31 32const displayTable = (table: Table) => 33 Effect.sync(() => { 34 console.log(table.padding(2).toString()); 35 }); 36 37const handleError = (error: DbError | Error) => 38 Effect.sync(() => { 39 console.error(`Failed to fetch volumes: ${error}`); 40 Deno.exit(1); 41 }); 42 43const lsEffect = () => 44 pipe( 45 Effect.all([listVolumes(), createTable()]), 46 Effect.flatMap(([volumes, table]) => populateTable(table, volumes)), 47 Effect.flatMap(displayTable), 48 Effect.catchAll(handleError), 49 ); 50 51export async function list() { 52 await Effect.runPromise(lsEffect()); 53} 54 55export async function remove(name: string) { 56 await Effect.runPromise( 57 pipe( 58 getVolume(name), 59 Effect.flatMap((volume) => 60 volume 61 ? deleteVolume(volume.id) 62 : Effect.fail(new Error(`Volume with name or ID ${name} not found.`)) 63 ), 64 Effect.tap(() => 65 Effect.sync(() => { 66 console.log(`Volume ${name} deleted successfully.`); 67 }) 68 ), 69 Effect.catchAll((error) => 70 Effect.sync(() => { 71 console.error(`An error occurred: ${error}`); 72 Deno.exit(1); 73 }) 74 ), 75 ), 76 ); 77} 78 79export async function inspect(name: string) { 80 await Effect.runPromise( 81 pipe( 82 getVolume(name), 83 Effect.flatMap((volume) => 84 volume 85 ? Effect.sync(() => { 86 console.log(volume); 87 }) 88 : Effect.fail(new Error(`Volume with name or ID ${name} not found.`)) 89 ), 90 Effect.catchAll((error) => 91 Effect.sync(() => { 92 console.error(`An error occurred: ${error}`); 93 Deno.exit(1); 94 }) 95 ), 96 ), 97 ); 98}