Compare commits
3 commits
Author | SHA1 | Date | |
---|---|---|---|
48a673dc09 | |||
0e323af9cf | |||
8970bd2895 |
2 changed files with 56 additions and 39 deletions
|
@ -2,7 +2,7 @@
|
|||
"name": "@endeavorance/rundir",
|
||||
"type": "module",
|
||||
"module": "src/cli.ts",
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.0",
|
||||
"bin": {
|
||||
"rundir": "build/cli.js"
|
||||
},
|
||||
|
|
93
src/cli.ts
93
src/cli.ts
|
@ -1,5 +1,4 @@
|
|||
import { existsSync } from "node:fs";
|
||||
import { homedir } from "node:os";
|
||||
import path from "node:path";
|
||||
import { parseArgs } from "node:util";
|
||||
import { $, Glob } from "bun";
|
||||
|
@ -20,13 +19,20 @@ class CLIError extends Error {
|
|||
}
|
||||
}
|
||||
|
||||
class NoRundirError extends CLIError {
|
||||
name = "NoRundirError";
|
||||
|
||||
constructor() {
|
||||
super("No rundir found in current directory tree");
|
||||
}
|
||||
}
|
||||
|
||||
const TEMPLATE_FILE_PATH = process.env["RUNDIR_TEMPLATE"] ?? null;
|
||||
const DEFAULT_TEMPLATE = `
|
||||
#!/usr/bin/env bash
|
||||
# Description...
|
||||
`.trim();
|
||||
const VERSION = pkg.version;
|
||||
const RUNDIR_PATH = path.join(process.cwd(), ".run");
|
||||
const COMMENT_STARTERS = ["#", "//", "--"];
|
||||
const COMMANDS = ["ls", "help", "new", "create", "which", "x", "run"] as const;
|
||||
type Command = (typeof COMMANDS)[number];
|
||||
|
@ -52,19 +58,19 @@ function parseCommand(command: string): Command {
|
|||
* @param fromPath The path to start searching from
|
||||
* @returns The path to the rundir, or null if not found
|
||||
*/
|
||||
function findNearestRundir(fromPath?: string): string | null {
|
||||
function getRundirPath(fromPath?: string): string {
|
||||
const currentDir = fromPath ?? process.cwd();
|
||||
const potentialPath = path.join(currentDir, ".run");
|
||||
const potentialPath = path.resolve(currentDir, ".run");
|
||||
|
||||
if (currentDir === path.dirname(currentDir)) {
|
||||
return null;
|
||||
throw new NoRundirError();
|
||||
}
|
||||
|
||||
if (existsSync(potentialPath)) {
|
||||
return potentialPath;
|
||||
}
|
||||
|
||||
return findNearestRundir(path.dirname(currentDir));
|
||||
return getRundirPath(path.dirname(currentDir));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -73,14 +79,12 @@ function findNearestRundir(fromPath?: string): string | null {
|
|||
* @param name The name of the script
|
||||
* @returns The absolute path to the script
|
||||
*/
|
||||
function makeScriptPath(name: string): string {
|
||||
const rundir = findNearestRundir();
|
||||
function getScriptPath(name: string): string {
|
||||
return path.resolve(getRundirPath(), name);
|
||||
}
|
||||
|
||||
if (!rundir) {
|
||||
throw new CLIError("No rundir found in the current directory tree.");
|
||||
}
|
||||
|
||||
return path.join(rundir, name);
|
||||
async function scriptExists(name: string): Promise<boolean> {
|
||||
return Bun.file(getScriptPath(name)).exists();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -94,22 +98,23 @@ function makeScriptPath(name: string): string {
|
|||
* @param name The name of the script to find the path of
|
||||
*/
|
||||
async function findScriptPath(name: string): Promise<string | null> {
|
||||
let currentDir = process.cwd();
|
||||
const currentRundir = getRundirPath();
|
||||
|
||||
while (currentDir !== path.dirname(currentDir)) {
|
||||
const potentialPath = path.join(currentDir, ".run", name);
|
||||
if (await Bun.file(potentialPath).exists()) {
|
||||
return potentialPath;
|
||||
}
|
||||
currentDir = path.dirname(currentDir);
|
||||
if (!currentRundir) {
|
||||
throw new NoRundirError();
|
||||
}
|
||||
|
||||
const homeDirPath = path.join(homedir(), ".run", name);
|
||||
if (await Bun.file(homeDirPath).exists()) {
|
||||
return homeDirPath;
|
||||
}
|
||||
const expectedPath = path.resolve(currentRundir, name);
|
||||
|
||||
const checkFile = Bun.file(expectedPath);
|
||||
|
||||
const exists = await checkFile.exists();
|
||||
|
||||
if (!exists) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return expectedPath;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -177,8 +182,9 @@ async function readScriptData(scriptName: string): Promise<ScriptData> {
|
|||
*/
|
||||
async function ls(scriptName?: string) {
|
||||
if (scriptName) {
|
||||
const pathname = await findScriptPath(scriptName);
|
||||
if (pathname === null) {
|
||||
const pathname = getScriptPath(scriptName);
|
||||
const exists = await scriptExists(pathname);
|
||||
if (!exists) {
|
||||
throw new CLIError(`Script "${scriptName}" not found.`);
|
||||
}
|
||||
|
||||
|
@ -186,7 +192,8 @@ async function ls(scriptName?: string) {
|
|||
return;
|
||||
}
|
||||
|
||||
const filesInDir = new Glob(`${RUNDIR_PATH}/*`).scan();
|
||||
const currentRundir = getRundirPath();
|
||||
const filesInDir = new Glob(`${currentRundir}/*`).scan();
|
||||
const scriptLines: string[] = [];
|
||||
|
||||
for await (const file of filesInDir) {
|
||||
|
@ -199,6 +206,7 @@ async function ls(scriptName?: string) {
|
|||
|
||||
const sorted = scriptLines.sort((a, b) => a.localeCompare(b));
|
||||
|
||||
console.log(chalk.dim(currentRundir));
|
||||
console.log(sorted.join("\n"));
|
||||
}
|
||||
|
||||
|
@ -207,14 +215,7 @@ async function ls(scriptName?: string) {
|
|||
* @command
|
||||
*/
|
||||
async function which() {
|
||||
const nearest = findNearestRundir();
|
||||
|
||||
if (!nearest) {
|
||||
console.error("No rundir found in the current directory tree.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(path.resolve(nearest));
|
||||
console.log(getRundirPath());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -222,7 +223,7 @@ async function which() {
|
|||
* @command
|
||||
*/
|
||||
async function newScript(name: string) {
|
||||
const scriptPath = makeScriptPath(name);
|
||||
const scriptPath = getScriptPath(name);
|
||||
const scriptFile = Bun.file(scriptPath);
|
||||
let template = DEFAULT_TEMPLATE;
|
||||
|
||||
|
@ -243,7 +244,7 @@ async function newScript(name: string) {
|
|||
|
||||
await Bun.write(scriptFile, template);
|
||||
await $`chmod +x ${scriptPath}`;
|
||||
console.log(name);
|
||||
console.log(scriptFile);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -258,7 +259,23 @@ async function runScript(name: string) {
|
|||
process.exit(1);
|
||||
}
|
||||
|
||||
await $`${scriptPath}`;
|
||||
const rundir = path.dirname(scriptPath);
|
||||
const cwd = path.resolve(rundir, "..");
|
||||
|
||||
const proc = Bun.spawn([scriptPath], {
|
||||
cwd,
|
||||
env: {
|
||||
...process.env,
|
||||
RUNDIR_PATH: rundir,
|
||||
RUNDIR_CWD: cwd,
|
||||
RUNDIR_SCRIPT_PATH: scriptPath,
|
||||
},
|
||||
stdout: Bun.stdout,
|
||||
stderr: Bun.stderr,
|
||||
stdin: Bun.stdin,
|
||||
});
|
||||
|
||||
await proc.exited;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue