alwaysai
Version:
The alwaysAI command-line interface (CLI)
128 lines (116 loc) • 3.1 kB
text/typescript
import { Spawner } from './types';
import { CodedError } from '@carnesen/coded-error';
import { Readable } from 'node:stream';
export function GnuSpawner(context: {
resolvePath: Spawner['resolvePath'];
run: Spawner['run'];
runForegroundSync: Spawner['runForegroundSync'];
runForeground: Spawner['runForeground'];
runStreaming: Spawner['runStreaming'];
}): Spawner {
const { resolvePath, run, runForegroundSync, runForeground, runStreaming } =
context;
return {
run,
runForegroundSync,
runForeground,
runStreaming,
resolvePath,
readdir,
walk,
async readFile(path) {
const output = await run({
exe: 'cat',
args: [resolvePath(path)]
});
return output;
},
async writeFile(path, data) {
await run({
exe: 'dd',
args: [`of=${resolvePath(path)}`],
input: Readable.from([data])
});
},
async rename(oldPath, newPath) {
await run({
exe: 'mv',
args: [resolvePath(oldPath), resolvePath(newPath)]
});
},
mkdirp,
rimraf,
sanatizedrimraf,
tar,
untar,
exists
};
async function mkdirp(path?: string) {
await run({ exe: 'mkdir', args: ['-p', resolvePath(path)] });
}
async function readdir(path?: string) {
let output: string;
const resolvedPath = resolvePath(path);
try {
output = await run({ exe: 'ls', args: ['-A1', resolvedPath] });
// ^^ The output looks like '/foo/bar.txt' if path is an existing file
// Else it looks like 'a b c' if the path is a directory with files/subdirs a, b, c.
} catch (ex) {
if (
ex &&
typeof ex.message === 'string' &&
ex.message.includes('No such file or directory')
) {
ex.code = 'ENOENT';
}
throw ex;
}
if (output.startsWith('/')) {
throw new CodedError(
`ENOTDIR: not a directory "${resolvedPath}"`,
'ENOTDIR'
);
}
return output.length > 0 ? output.split('\n') : [];
}
async function rimraf(path?: string) {
await run({ exe: 'rm', args: ['-rf', resolvePath(path)] });
}
async function sanatizedrimraf(path?: string) {
const sanatizedPath = resolvePath(path).replace('*', '');
await run({ exe: 'rm', args: ['-rf', sanatizedPath] });
}
async function tar(...paths: string[]) {
return await runStreaming({
exe: 'tar',
args: ['-cz', ...paths],
cwd: resolvePath()
});
}
async function untar(input: Readable, cwd = '.') {
await run({
exe: 'tar',
args: ['-xz'],
cwd,
input
});
}
async function exists(path: string) {
if (!path) {
throw new Error('"path" is required');
}
try {
await run({ exe: 'stat', args: [resolvePath(path)] });
return true;
} catch (ex) {
return false;
}
}
async function walk(dir?: string): Promise<string[]> {
throw new Error(
`NotImplementedError: GnuSpawner 'walk' function not available. Please use JsSpawner. Args: ${
dir ?? 'None'
}`
);
}
}