scroll/src/common/runtime.ts

139 lines
3.1 KiB
JavaScript

import { IRuntime, ITestBase } from './types.ts';
import { getTermios } from './termios.ts';
import { noop } from './fns.ts';
import { SCROLL_ERR_FILE, SCROLL_LOG_FILE } from './config.ts';
export type { IFFI, IFileIO, IRuntime, ITerminal } from './types.ts';
/**
* Which Typescript runtime is currently being used
*/
export enum RunTimeType {
Bun = 'bun',
Deno = 'deno',
Unknown = 'common',
}
export enum LogLevel {
Debug = 'Debug',
Info = 'Info',
Notice = 'Notice',
Warning = 'Warning',
Error = 'Error',
}
let scrollRuntime: IRuntime | null = null;
// ----------------------------------------------------------------------------
// Misc runtime functions
// ----------------------------------------------------------------------------
export function log(s: unknown, level: LogLevel = LogLevel.Notice): void {
getRuntime().then(({ file }) => {
const raw = typeof s === 'string' ? s : JSON.stringify(s, null, 2);
const output = `${level}: ${raw}\n`;
const outputFile = (level === LogLevel.Error)
? SCROLL_ERR_FILE
: SCROLL_LOG_FILE;
file.appendFile(outputFile, output).then(noop);
});
}
/**
* Append information to the scroll.err logfile
*/
export function logError(s: unknown): void {
log(s, LogLevel.Error);
}
/**
* Kill program, displaying an error message
* @param s
*/
export function die(s: string | Error): void {
logError(s);
getTermios().then((t) => {
t.disableRawMode();
t.cleanup();
console.error(s);
getRuntime().then((r) => r.exit());
});
}
/**
* Determine which Typescript runtime we are operating under
*/
export function runtimeType(): RunTimeType {
let runtime = RunTimeType.Unknown;
if ('Deno' in globalThis) {
runtime = RunTimeType.Deno;
}
if ('Bun' in globalThis) {
runtime = RunTimeType.Bun;
}
return runtime;
}
/**
* Get the adapter object for the current Runtime
*/
export async function getRuntime(): Promise<IRuntime> {
if (scrollRuntime === null) {
const runtime = runtimeType();
const path = `../${runtime}/mod.ts`;
const pkg = await import(path);
if ('default' in pkg) {
scrollRuntime = pkg.default;
}
}
return Promise.resolve(scrollRuntime!);
}
/**
* Get the common test interface object
*/
export async function getTestRunner(): Promise<ITestBase> {
const runtime = runtimeType();
const path = `../${runtime}/test_base.ts`;
const pkg = await import(path);
if ('default' in pkg) {
return pkg.default;
}
return pkg;
}
/**
* Import a runtime-specific module
*
* e.g. to load "src/bun/mod.ts", if the runtime is bun,
* you can use like so `await importForRuntime('index')`;
*
* @param path - the path within the runtime module
*/
export const importForRuntime = async (path: string) => {
const runtime = runtimeType();
const suffix = '.ts';
const base = `../${runtime}/`;
const pathParts = path
.split('/')
.filter((part) => part !== '' && part !== '.' && part !== suffix)
.map((part) => part.replace(suffix, ''));
const cleanedPath = pathParts.join('/');
const importPath = base + cleanedPath + suffix;
const pkg = await import(importPath);
if ('default' in pkg) {
return pkg.default;
}
return pkg;
};