formatting and tidying

This commit is contained in:
Conduitry 2018-10-11 10:45:37 -04:00
parent 92a1940348
commit d7cb64c947
4 changed files with 58 additions and 106 deletions

View File

@ -1,11 +1,13 @@
import { readFile } from './fs';
import { Stats } from 'fs';
import * as fs from 'fs';
import { resolve } from 'path';
import { promisify } from 'util';
import File from './File';
import Watcher, { WatcherEvent } from './Watcher';
import * as context from './context';
const readFile = promisify(fs.readFile);
export default class Defiler {
// set of original paths for all physical files
paths = new Set<string>();
@ -39,16 +41,11 @@ export default class Defiler {
private _endWave: () => void = null;
constructor(...args: any[]) {
const { transform, generators = [], resolver, onerror } = <DefilerData>(
args.pop()
);
const { transform, generators = [], resolver, onerror } = <DefilerData>args.pop();
if (typeof transform !== 'function') {
throw new TypeError('defiler: transform must be a function');
}
if (
!Array.isArray(generators) ||
generators.some(generator => typeof generator !== 'function')
) {
if (!Array.isArray(generators) || generators.some(generator => typeof generator !== 'function')) {
throw new TypeError('defiler: generators must be an array of functions');
}
if (resolver && typeof resolver !== 'function') {
@ -57,44 +54,30 @@ export default class Defiler {
if (onerror && typeof onerror !== 'function') {
throw new TypeError('defiler: onerror must be a function');
}
this._watchers = args.map(
({
dir,
filter,
read = true,
enc = 'utf8',
pre,
watch = true,
debounce = 10,
}) => {
if (typeof dir !== 'string') {
throw new TypeError('defiler: dir must be a string');
}
if (filter && typeof filter !== 'function') {
throw new TypeError('defiler: filter must be a function');
}
if (typeof read !== 'boolean' && typeof read !== 'function') {
throw new TypeError('defiler: read must be a boolean or a function');
}
if (!Buffer.isEncoding(enc) && typeof enc !== 'function') {
throw new TypeError(
'defiler: enc must be a supported encoding or a function',
);
}
if (pre && typeof pre !== 'function') {
throw new TypeError('defiler: pre must be a function');
}
if (typeof watch !== 'boolean') {
throw new TypeError('defiler: watch must be a boolean');
}
if (typeof debounce !== 'number') {
throw new TypeError('defiler: debounce must be a number');
}
return <WatcherData>(
new Watcher({ dir, filter, read, enc, pre, watch, debounce })
);
},
);
this._watchers = args.map(({ dir, filter, read = true, enc = 'utf8', pre, watch = true, debounce = 10 }) => {
if (typeof dir !== 'string') {
throw new TypeError('defiler: dir must be a string');
}
if (filter && typeof filter !== 'function') {
throw new TypeError('defiler: filter must be a function');
}
if (typeof read !== 'boolean' && typeof read !== 'function') {
throw new TypeError('defiler: read must be a boolean or a function');
}
if (!Buffer.isEncoding(enc) && typeof enc !== 'function') {
throw new TypeError('defiler: enc must be a supported encoding or a function');
}
if (pre && typeof pre !== 'function') {
throw new TypeError('defiler: pre must be a function');
}
if (typeof watch !== 'boolean') {
throw new TypeError('defiler: watch must be a boolean');
}
if (typeof debounce !== 'number') {
throw new TypeError('defiler: debounce must be a number');
}
return <WatcherData>new Watcher({ dir, filter, read, enc, pre, watch, debounce });
});
this._transform = transform;
this._generators = generators;
this._resolver = resolver;
@ -110,7 +93,7 @@ export default class Defiler {
this._isProcessing = true;
const done = this._startWave();
// init the Watcher instances
const files: [WatcherData, string, { path: string; stats: Stats }][] = [];
const files: [WatcherData, string, { path: string; stats: fs.Stats }][] = [];
await Promise.all(
this._watchers.map(async watcher => {
watcher.dir = resolve(watcher.dir);
@ -159,19 +142,13 @@ export default class Defiler {
return Promise.all(_.map(path => this.get(path)));
}
if (typeof _ !== 'string' && typeof _ !== 'function') {
throw new TypeError(
'defiler.get: argument must be a string, an array, or a function',
);
throw new TypeError('defiler.get: argument must be a string, an array, or a function');
}
const current = <Name>context.current();
if (current) {
this._deps.push([current, _]);
}
if (
this._status === Status.During &&
current &&
(typeof _ === 'function' || !this.files.has(_))
) {
if (this._status === Status.During && current && (typeof _ === 'function' || !this.files.has(_))) {
if (this._whenFound.has(_)) {
const { promise, paths } = this._whenFound.get(_);
paths.push(current);
@ -183,9 +160,7 @@ export default class Defiler {
await promise;
}
}
return typeof _ === 'function'
? this.get([...this.files.keys()].filter(_).sort())
: this.files.get(_);
return typeof _ === 'function' ? this.get([...this.files.keys()].filter(_).sort()) : this.files.get(_);
}
// add a new virtual file
@ -203,9 +178,7 @@ export default class Defiler {
// resolve a given path from the file currently being transformed
resolve(path: string): string {
return this._resolver && typeof context.current() === 'string'
? this._resolver(context.current(), path)
: path;
return this._resolver && typeof context.current() === 'string' ? this._resolver(context.current(), path) : path;
}
// private methods
@ -216,10 +189,7 @@ export default class Defiler {
}
// add a Watcher event to the queue, and handle queued events
private async _enqueue(
watcher?: WatcherData,
event?: WatcherEvent,
): Promise<void> {
private async _enqueue(watcher?: WatcherData, event?: WatcherEvent): Promise<void> {
if (event) {
this._queue.push([watcher, event]);
}
@ -251,11 +221,7 @@ export default class Defiler {
}
// create a file object for a physical file and process it
private async _processPhysicalFile(
{ dir, read, enc }: WatcherData,
path: string,
file: FileData,
): Promise<void> {
private async _processPhysicalFile({ dir, read, enc }: WatcherData, path: string, file: FileData): Promise<void> {
if (typeof read === 'function') {
read = await read({ path, stats: file.stats });
}
@ -320,9 +286,7 @@ export default class Defiler {
private _processDependents(path: string): void {
const dependents = new Set<Name>();
for (const [dependent, dependency] of this._deps) {
if (
typeof dependency === 'string' ? dependency === path : dependency(path)
) {
if (typeof dependency === 'string' ? dependency === path : dependency(path)) {
dependents.add(dependent);
}
}
@ -432,10 +396,8 @@ interface Transform {
}
interface WatcherData extends Watcher {
read: boolean | ((arg: { path: string; stats: Stats }) => Promise<boolean>);
enc:
| string
| ((arg: { path: string; stats: Stats; bytes: Buffer }) => Promise<string>);
read: boolean | ((arg: { path: string; stats: fs.Stats }) => Promise<boolean>);
enc: string | ((arg: { path: string; stats: fs.Stats; bytes: Buffer }) => Promise<string>);
pre: (data: FileData) => Promise<void>;
}

View File

@ -1,4 +1,4 @@
import { Stats } from 'fs';
import * as fs from 'fs';
export default class File {
// path of file
@ -10,7 +10,7 @@ export default class File {
// cached ext
private _ext: string = null;
// stats of file
stats: Stats = null;
stats: fs.Stats = null;
// encoding
private _enc: string = 'utf8';
// Buffer of file contents
@ -60,8 +60,7 @@ export default class File {
throw new TypeError('file.filename must be a string');
}
const old = this.filename;
this.path =
(old ? this._path.slice(0, -old.length) : this._path) + filename;
this.path = (old ? this._path.slice(0, -old.length) : this._path) + filename;
}
get ext(): string {
@ -93,9 +92,7 @@ export default class File {
}
get bytes(): Buffer {
return this._bytes == null && this._text != null
? (this._bytes = Buffer.from(this._text, this._enc))
: this._bytes;
return this._bytes == null && this._text != null ? (this._bytes = Buffer.from(this._text, this._enc)) : this._bytes;
}
set bytes(bytes: Buffer) {
@ -107,9 +104,7 @@ export default class File {
}
get text(): string {
return this._text == null && this._bytes != null
? (this._text = this._bytes.toString(this._enc))
: this._text;
return this._text == null && this._bytes != null ? (this._text = this._bytes.toString(this._enc)) : this._text;
}
set text(text: string) {

View File

@ -1,20 +1,23 @@
import * as EventEmitter from 'events';
import { stat, readdir } from './fs';
import { watch, FSWatcher, Stats } from 'fs';
import * as fs from 'fs';
import { promisify } from 'util';
const readdir = promisify(fs.readdir);
const stat = promisify(fs.stat);
export default class Watcher extends EventEmitter {
dir: string;
filter: (file: { path: string; stats: Stats }) => boolean;
filter: (file: { path: string; stats: fs.Stats }) => boolean;
watch: boolean;
debounce: number;
// paths of all directories -> FSWatcher instances
private _watchers = new Map<string, FSWatcher>();
private _watchers = new Map<string, fs.FSWatcher>();
// paths of all files -> file stats
private _stats = new Map<string, Stats>();
private _stats = new Map<string, fs.Stats>();
// paths of files with pending debounced events -> setTimeout timer ids
private _timeouts = new Map<string, NodeJS.Timer>();
// queue of pending FSWatcher events to handle
private _queue = new Array<string>();
private _queue: string[] = [];
// whether some FSWatcher event is currently already in the process of being handled
private _isProcessing: boolean = false;
@ -25,7 +28,7 @@ export default class Watcher extends EventEmitter {
// recurse directory, get stats, set up FSWatcher instances
// returns array of { path, stats }
async init(): Promise<{ path: string; stats: Stats }[]> {
async init(): Promise<{ path: string; stats: fs.Stats }[]> {
await this._recurse(this.dir);
return [...this._stats.entries()].map(([path, stats]) => ({
path,
@ -44,11 +47,9 @@ export default class Watcher extends EventEmitter {
this._stats.set(path, stats);
} else if (stats.isDirectory()) {
if (this.watch) {
this._watchers.set(path, watch(full, this._handle.bind(this, full)));
this._watchers.set(path, fs.watch(full, this._handle.bind(this, full)));
}
await Promise.all(
(await readdir(full)).map(sub => this._recurse(full + '/' + sub)),
);
await Promise.all((await readdir(full)).map(sub => this._recurse(full + '/' + sub)));
}
}
@ -125,5 +126,5 @@ export default class Watcher extends EventEmitter {
export interface WatcherEvent {
event: string;
path: string;
stats?: Stats;
stats?: fs.Stats;
}

View File

@ -1,6 +0,0 @@
import * as fs from 'fs';
import { promisify } from 'util';
export const readdir = promisify(fs.readdir);
export const readFile = promisify(fs.readFile);
export const stat = promisify(fs.stat);