@stryker-mutator/core
Version:
The extendable JavaScript mutation testing framework
60 lines (50 loc) • 1.75 kB
text/typescript
import fs from 'fs';
import { Task } from '@stryker-mutator/util';
import { mergeMap, Subject } from 'rxjs';
import { Disposable } from 'typed-inject';
const MAX_CONCURRENT_FILE_IO = 256;
class FileSystemAction<TOut> {
public readonly task = new Task<TOut>();
/**
* @param work The task, where a resource and input is presented
*/
constructor(private readonly work: () => Promise<TOut>) {}
public async execute() {
try {
const output = await this.work();
this.task.resolve(output);
} catch (err) {
this.task.reject(err);
}
}
}
/**
* A wrapper around nodejs's 'fs' core module, for dependency injection purposes.
*
* Also has build-in buffering support with a concurrency limit (like "graceful-fs").
*/
export class FileSystem implements Disposable {
private readonly todoSubject = new Subject<FileSystemAction<any>>();
private readonly subscription = this.todoSubject
.pipe(
mergeMap(async (action) => {
await action.execute();
}, MAX_CONCURRENT_FILE_IO),
)
.subscribe();
public dispose(): void {
this.subscription.unsubscribe();
}
public readonly readFile = this.forward('readFile');
public readonly copyFile = this.forward('copyFile');
public readonly writeFile = this.forward('writeFile');
public readonly mkdir = this.forward('mkdir');
public readonly readdir = this.forward('readdir');
private forward<TMethod extends keyof Omit<typeof fs.promises, 'constants'>>(method: TMethod): (typeof fs.promises)[TMethod] {
return (...args: any[]) => {
const action = new FileSystemAction(() => (fs.promises[method] as any)(...args));
this.todoSubject.next(action);
return action.task.promise as any;
};
}
}