Comparing version 0.13.5 to 0.14.0
@@ -0,1 +1,7 @@ | ||
# v0.14.0 | ||
- Allow per-file and per-directory filtering of which files to consider | ||
- Allow `read` and `enc` settings to be determined per file | ||
- Remove `file.paths` | ||
# v0.13.5 | ||
@@ -15,3 +21,3 @@ | ||
- If a file change event comes in during the first wave of processing, don't wait for another event after the first wave to trigger the second wave, and instead start it immediately upon finishing the first. | ||
- If a file change event comes in during the first wave of processing, don't wait for another event after the first wave to trigger the second wave, and instead start it immediately upon finishing the first | ||
@@ -18,0 +24,0 @@ # v0.13.1 |
@@ -5,7 +5,5 @@ 'use strict'; | ||
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } | ||
var fs = require('fs'); | ||
var util = require('util'); | ||
var EventEmitter = _interopDefault(require('events')); | ||
var EventEmitter = require('events'); | ||
var path = require('path'); | ||
@@ -19,13 +17,10 @@ | ||
constructor() { | ||
Object.assign(this, { | ||
[_path]: null, // path of file | ||
[_dir]: null, //cached dir | ||
[_filename]: null, // cached filename | ||
[_ext]: null, // cached ext | ||
paths: [], // all historical paths of file | ||
stats: null, // stats of file | ||
[_enc]: 'utf8', // encoding | ||
[_bytes]: null, // Buffer of file contents | ||
[_text]: null, // string of file contents | ||
}); | ||
this[_path] = null; // path of file | ||
this[_dir] = null; // cached dir | ||
this[_filename] = null; // cached filename | ||
this[_ext] = null; // cached ext | ||
this.stats = null; // stats of file | ||
this[_enc] = 'utf8'; // encoding | ||
this[_bytes] = null; // Buffer of file contents | ||
this[_text] = null; // string of file contents | ||
} | ||
@@ -42,3 +37,2 @@ | ||
this[_dir] = this[_filename] = this[_ext] = null; | ||
this.paths.push(path$$1); | ||
} | ||
@@ -105,3 +99,5 @@ } | ||
set bytes(bytes) { | ||
if (!Buffer.isBuffer(bytes)) throw new TypeError('file.bytes must be a Buffer') | ||
if (bytes != null && !Buffer.isBuffer(bytes)) { | ||
throw new TypeError('file.bytes must be a Buffer or null') | ||
} | ||
this[_bytes] = bytes; | ||
@@ -118,3 +114,5 @@ this[_text] = null; | ||
set text(text) { | ||
if (typeof text !== 'string') throw new TypeError('file.text must be a string') | ||
if (text != null && typeof text !== 'string') { | ||
throw new TypeError('file.text must be a string or null') | ||
} | ||
this[_text] = text; | ||
@@ -132,11 +130,10 @@ this[_bytes] = null; | ||
class Watcher extends EventEmitter { | ||
constructor(data /* = { dir, watch, debounce } */) { | ||
constructor(data /* = { dir, filter, watch, debounce } */) { | ||
super(); | ||
Object.assign(this, data, { | ||
[_watchers]: new Map(), // paths of all (recursive) directories -> FSWatcher instances | ||
[_stats]: new Map(), // paths of all (recursive) files -> file stats | ||
[_timeouts]: new Map(), // paths of (recursive) files with pending debounced events -> setTimeout timer ids | ||
[_queue]: [], // queue of pending FSWatcher events to handle | ||
[_isProcessing]: false, // whether some FSWatcher event is currently already in the process of being handled | ||
}); | ||
Object.assign(this, data); | ||
this[_watchers] = new Map(); // paths of all directories -> FSWatcher instances | ||
this[_stats] = new Map(); // paths of all files -> file stats | ||
this[_timeouts] = new Map(); // paths of files with pending debounced events -> setTimeout timer ids | ||
this[_queue] = []; // queue of pending FSWatcher events to handle | ||
this[_isProcessing] = false; // whether some FSWatcher event is currently already in the process of being handled | ||
} | ||
@@ -155,2 +152,3 @@ | ||
let stats = await stat(full); | ||
if (this.filter && !await this.filter({ path: path$$1, stats })) return | ||
if (stats.isFile()) { | ||
@@ -187,2 +185,3 @@ this[_stats].set(path$$1, stats); | ||
let stats = await stat(full); | ||
if (this.filter && !await this.filter({ path: path$$1, stats })) continue | ||
if (stats.isFile()) { | ||
@@ -196,5 +195,3 @@ // note the new/changed file | ||
for (let [newPath, stats] of this[_stats].entries()) { | ||
if (newPath.startsWith(path$$1 + '/')) { | ||
this.emit('', { event: '+', path: newPath, stats }); | ||
} | ||
if (newPath.startsWith(path$$1 + '/')) this.emit('', { event: '+', path: newPath, stats }); | ||
} | ||
@@ -230,3 +227,3 @@ } | ||
// prettier-ignore | ||
let { _origData, _status, _watcher, _transform, _generators, _resolver, _active, _waitingFor, _whenFound, _dependencies, _queue: _queue$1, _isProcessing: _isProcessing$1, _startWave, _endWave, _enqueue: _enqueue$1, _processPhysicalFile, _processFile, _processGenerator, _cur, _newProxy, _processDependents, _markFound } = symbols; | ||
let { _origData, _status, _watcher, _transform, _generators, _resolver, _active, _waitingFor, _whenFound, _deps, _queue: _queue$1, _isProcessing: _isProcessing$1, _startWave, _endWave, _enqueue: _enqueue$1, _processPhysicalFile, _processFile, _processGenerator, _cur, _newProxy, _processDependents, _markFound } = symbols; | ||
@@ -236,2 +233,3 @@ class Defiler extends EventEmitter { | ||
dir, | ||
filter, | ||
read = true, | ||
@@ -246,4 +244,11 @@ enc = 'utf8', | ||
if (typeof dir !== 'string') throw new TypeError('defiler: dir must be a string') | ||
if (typeof read !== 'boolean') throw new TypeError('defiler: read must be a boolean') | ||
if (!Buffer.isEncoding(enc)) throw new TypeError('defiler: enc must be a supported encoding') | ||
if (typeof filter !== 'undefined' && 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 (typeof watch !== 'boolean') throw new TypeError('defiler: watch must be a boolean') | ||
@@ -260,20 +265,21 @@ if (typeof debounce !== 'number') throw new TypeError('defiler: debounce must be a number') | ||
} | ||
if (typeof resolver !== 'undefined' && typeof resolver !== 'function') { | ||
throw new TypeError('defiler: resolver must be a function') | ||
} | ||
super(); | ||
Object.assign(this, { | ||
paths: new Set(), // set of original paths for all physical files | ||
[_origData]: new Map(), // original paths -> original file data for all physical files ({ path, stats, bytes, enc }) | ||
files: new Map(), // original paths -> transformed files for all physical and virtual files | ||
[_status]: null, // null = exec not called; false = exec pending; true = exec finished | ||
[_watcher]: new Watcher({ dir: path.resolve(dir), read, enc, watch, debounce }), // Watcher instance | ||
[_transform]: transform, // the transform to run on all files | ||
[_generators]: new Map(generators.map(generator => [Symbol(), generator])), // unique symbols -> registered generators | ||
[_resolver]: resolver, // (base, path) => path resolver function, used in defiler.get and defiler.add from transform | ||
[_active]: new Set(), // original paths of all files currently undergoing transformation and symbols of all generators currently running | ||
[_waitingFor]: new Map(), // original paths -> number of other files they're currently waiting on to exist | ||
[_whenFound]: new Map(), // original paths -> { promise, resolve } objects for when awaited files become available | ||
[_cur]: { root: null, dep: null }, // (set via proxy) root: the current root dependent, for use in _dependencies; dep: the current immediate dependent, for use in _waitingFor | ||
[_dependencies]: new Map(), // original paths of dependents -> set of original paths of dependencies, specifying changes to which files should trigger re-processing which other files | ||
[_queue$1]: [], // queue of pending Watcher events to handle | ||
[_isProcessing$1]: false, // whether some Watcher event is currently already in the process of being handled | ||
}); | ||
this.paths = new Set(); // set of original paths for all physical files | ||
this[_origData] = new Map(); // original paths -> original file data for all physical files ({ path, stats, bytes, enc }) | ||
this.files = new Map(); // original paths -> transformed files for all physical and virtual files | ||
this[_status] = null; // null = exec not called; false = exec pending; true = exec finished | ||
this[_watcher] = new Watcher({ dir: path.resolve(dir), filter, read, enc, watch, debounce }); // Watcher instance | ||
this[_transform] = transform; // the transform to run on all files | ||
this[_generators] = new Map(generators.map(generator => [Symbol(), generator])); // unique symbols -> registered generators | ||
this[_resolver] = resolver; // (base, path) => path resolver function, used in defiler.get and defiler.add from transform | ||
this[_active] = new Set(); // original paths of all files currently undergoing transformation and symbols of all generators currently running | ||
this[_waitingFor] = new Map(); // original paths -> number of other files they're currently waiting on to exist | ||
this[_whenFound] = new Map(); // original paths -> { promise, resolve } objects for when awaited files become available | ||
this[_cur] = { root: null, parent: null }; // (set via proxy) root: the current root dependent, for use in _deps; parent: the current immediate dependent, for use in _waitingFor and the resolver | ||
this[_deps] = []; // array of [dependent, dependency] pairs, specifying changes to which files should trigger re-processing which other files | ||
this[_queue$1] = []; // queue of pending Watcher events to handle | ||
this[_isProcessing$1] = false; // whether some Watcher event is currently already in the process of being handled | ||
} | ||
@@ -309,19 +315,9 @@ | ||
async get(path$$1) { | ||
if ( | ||
typeof path$$1 !== 'string' && | ||
(!Array.isArray(path$$1) || path$$1.some(path$$1 => typeof path$$1 !== 'string')) | ||
) { | ||
throw new TypeError('defiler.get: path must be a string or an array of strings') | ||
} | ||
if (Array.isArray(path$$1)) return Promise.all(path$$1.map(path$$1 => this.get(path$$1))) | ||
let { [_cur]: cur, [_waitingFor]: waitingFor } = this; | ||
if (this[_resolver] && typeof cur.dep === 'string') { | ||
path$$1 = this[_resolver](cur.dep, path$$1); | ||
} | ||
if (cur.root) { | ||
if (!this[_dependencies].has(cur.root)) this[_dependencies].set(cur.root, new Set()); | ||
this[_dependencies].get(cur.root).add(path$$1); | ||
} | ||
if (this[_resolver] && typeof cur.parent === 'string') path$$1 = this[_resolver](cur.parent, path$$1); | ||
if (typeof path$$1 !== 'string') throw new TypeError('defiler.get: path must be a string') | ||
if (cur.root) this[_deps].push([cur.root, path$$1]); | ||
if (!this[_status] && !this.files.has(path$$1)) { | ||
if (cur.dep) waitingFor.set(cur.dep, (waitingFor.get(cur.dep) || 0) + 1); | ||
if (cur.parent) waitingFor.set(cur.parent, (waitingFor.get(cur.parent) || 0) + 1); | ||
if (!this[_whenFound].has(path$$1)) { | ||
@@ -332,3 +328,3 @@ let resolve; | ||
await this[_whenFound].get(path$$1).promise; | ||
if (cur.dep) waitingFor.set(cur.dep, waitingFor.get(cur.dep) - 1); | ||
if (cur.parent) waitingFor.set(cur.parent, waitingFor.get(cur.parent) - 1); | ||
} | ||
@@ -338,8 +334,8 @@ return this.files.get(path$$1) | ||
// add a new non-physical file | ||
// add a new virtual file | ||
add(file) { | ||
if (this[_status] === null) throw new Error('defiler.add: cannot call before calling exec') | ||
if (typeof file !== 'object') throw new TypeError('defiler.add: file must be an object') | ||
if (this[_resolver] && typeof this[_cur].dep === 'string') { | ||
file.path = this[_resolver](this[_cur].dep, file.path); | ||
if (this[_resolver] && typeof this[_cur].parent === 'string') { | ||
file.path = this[_resolver](this[_cur].parent, file.path); | ||
} | ||
@@ -372,3 +368,3 @@ this[_processFile](file); | ||
this.emit('deleted', { defiler: this, file }); | ||
this[_processDependents](path$$1); | ||
if (this[_status]) this[_processDependents](path$$1); | ||
} | ||
@@ -383,4 +379,7 @@ await done; | ||
let { dir, read, enc } = this[_watcher]; | ||
let data = { path: path$$1, stats, enc }; | ||
if (read) data.bytes = await readFile(dir + '/' + path$$1); | ||
let data = { path: path$$1, stats }; | ||
if (read && (typeof read !== 'function' || (await read({ path: path$$1, stats })))) { | ||
data.bytes = await readFile(dir + '/' + path$$1); | ||
} | ||
data.enc = typeof enc === 'function' ? await enc({ path: path$$1, stats, bytes: data.bytes }) : enc; | ||
this.paths.add(path$$1); | ||
@@ -393,10 +392,11 @@ this[_origData].set(path$$1, data); | ||
// transform a file, store it, and process dependents | ||
async [_processFile](file) { | ||
file = Object.assign(new File(), file); | ||
async [_processFile](data) { | ||
let file = Object.assign(new File(), data); | ||
let { path: path$$1 } = file; | ||
this[_active].add(path$$1); | ||
let defiler = this[_newProxy](path$$1); | ||
try { | ||
await this[_transform]({ defiler: this[_newProxy](path$$1), file }); | ||
await this[_transform]({ defiler, file }); | ||
} catch (error) { | ||
this.emit('error', { defiler: this, file, error }); | ||
this.emit('error', { defiler, file, error }); | ||
} | ||
@@ -406,3 +406,3 @@ this.files.set(path$$1, file); | ||
this[_markFound](path$$1); | ||
this[_processDependents](path$$1); | ||
if (this[_status]) this[_processDependents](path$$1); | ||
this[_active].delete(path$$1); | ||
@@ -420,10 +420,4 @@ if (!this[_active].size) { | ||
[_processDependents](path$$1) { | ||
if (!this[_status]) return | ||
let dependents = new Set(); | ||
for (let [dependent, dependencies] of this[_dependencies].entries()) { | ||
if (dependencies.has(path$$1)) { | ||
dependents.add(dependent); | ||
this[_dependencies].delete(dependent); | ||
} | ||
} | ||
let dependents = new Set(this[_deps].map(([dependent, dep]) => dep === path$$1 && dependent)); | ||
this[_deps] = this[_deps].filter(([dependent]) => !dependents.has(dependent)); | ||
if (!dependents.size && !this[_active].size) this[_endWave](); | ||
@@ -443,6 +437,7 @@ for (let dependent of dependents) { | ||
let generator = this[_generators].get(symbol); | ||
let defiler = this[_newProxy](symbol); | ||
try { | ||
await generator({ defiler: this[_newProxy](symbol) }); | ||
await generator({ defiler }); | ||
} catch (error) { | ||
this.emit('error', { defiler: this, generator, error }); | ||
this.emit('error', { defiler, generator, error }); | ||
} | ||
@@ -452,5 +447,5 @@ this[_active].delete(symbol); | ||
// create a defiler Proxy for the given path, always overriding _cur.dep and only overriding _cur.root if it is not yet set | ||
// create a defiler Proxy for the given path, always overriding _cur.parent and only overriding _cur.root if it is not yet set | ||
[_newProxy](path$$1) { | ||
let cur = { root: this[_cur].root || path$$1, dep: path$$1 }; | ||
let cur = { root: this[_cur].root || path$$1, parent: path$$1 }; | ||
return new Proxy(this, { get: (_, key) => (key === _cur ? cur : this[key]) }) | ||
@@ -457,0 +452,0 @@ } |
@@ -12,13 +12,10 @@ import { readdir, readFile, stat, watch } from 'fs'; | ||
constructor() { | ||
Object.assign(this, { | ||
[_path]: null, // path of file | ||
[_dir]: null, //cached dir | ||
[_filename]: null, // cached filename | ||
[_ext]: null, // cached ext | ||
paths: [], // all historical paths of file | ||
stats: null, // stats of file | ||
[_enc]: 'utf8', // encoding | ||
[_bytes]: null, // Buffer of file contents | ||
[_text]: null, // string of file contents | ||
}); | ||
this[_path] = null; // path of file | ||
this[_dir] = null; // cached dir | ||
this[_filename] = null; // cached filename | ||
this[_ext] = null; // cached ext | ||
this.stats = null; // stats of file | ||
this[_enc] = 'utf8'; // encoding | ||
this[_bytes] = null; // Buffer of file contents | ||
this[_text] = null; // string of file contents | ||
} | ||
@@ -35,3 +32,2 @@ | ||
this[_dir] = this[_filename] = this[_ext] = null; | ||
this.paths.push(path); | ||
} | ||
@@ -98,3 +94,5 @@ } | ||
set bytes(bytes) { | ||
if (!Buffer.isBuffer(bytes)) throw new TypeError('file.bytes must be a Buffer') | ||
if (bytes != null && !Buffer.isBuffer(bytes)) { | ||
throw new TypeError('file.bytes must be a Buffer or null') | ||
} | ||
this[_bytes] = bytes; | ||
@@ -111,3 +109,5 @@ this[_text] = null; | ||
set text(text) { | ||
if (typeof text !== 'string') throw new TypeError('file.text must be a string') | ||
if (text != null && typeof text !== 'string') { | ||
throw new TypeError('file.text must be a string or null') | ||
} | ||
this[_text] = text; | ||
@@ -125,11 +125,10 @@ this[_bytes] = null; | ||
class Watcher extends EventEmitter { | ||
constructor(data /* = { dir, watch, debounce } */) { | ||
constructor(data /* = { dir, filter, watch, debounce } */) { | ||
super(); | ||
Object.assign(this, data, { | ||
[_watchers]: new Map(), // paths of all (recursive) directories -> FSWatcher instances | ||
[_stats]: new Map(), // paths of all (recursive) files -> file stats | ||
[_timeouts]: new Map(), // paths of (recursive) files with pending debounced events -> setTimeout timer ids | ||
[_queue]: [], // queue of pending FSWatcher events to handle | ||
[_isProcessing]: false, // whether some FSWatcher event is currently already in the process of being handled | ||
}); | ||
Object.assign(this, data); | ||
this[_watchers] = new Map(); // paths of all directories -> FSWatcher instances | ||
this[_stats] = new Map(); // paths of all files -> file stats | ||
this[_timeouts] = new Map(); // paths of files with pending debounced events -> setTimeout timer ids | ||
this[_queue] = []; // queue of pending FSWatcher events to handle | ||
this[_isProcessing] = false; // whether some FSWatcher event is currently already in the process of being handled | ||
} | ||
@@ -148,2 +147,3 @@ | ||
let stats = await stat$1(full); | ||
if (this.filter && !await this.filter({ path, stats })) return | ||
if (stats.isFile()) { | ||
@@ -180,2 +180,3 @@ this[_stats].set(path, stats); | ||
let stats = await stat$1(full); | ||
if (this.filter && !await this.filter({ path, stats })) continue | ||
if (stats.isFile()) { | ||
@@ -189,5 +190,3 @@ // note the new/changed file | ||
for (let [newPath, stats] of this[_stats].entries()) { | ||
if (newPath.startsWith(path + '/')) { | ||
this.emit('', { event: '+', path: newPath, stats }); | ||
} | ||
if (newPath.startsWith(path + '/')) this.emit('', { event: '+', path: newPath, stats }); | ||
} | ||
@@ -223,3 +222,3 @@ } | ||
// prettier-ignore | ||
let { _origData, _status, _watcher, _transform, _generators, _resolver, _active, _waitingFor, _whenFound, _dependencies, _queue: _queue$1, _isProcessing: _isProcessing$1, _startWave, _endWave, _enqueue: _enqueue$1, _processPhysicalFile, _processFile, _processGenerator, _cur, _newProxy, _processDependents, _markFound } = symbols; | ||
let { _origData, _status, _watcher, _transform, _generators, _resolver, _active, _waitingFor, _whenFound, _deps, _queue: _queue$1, _isProcessing: _isProcessing$1, _startWave, _endWave, _enqueue: _enqueue$1, _processPhysicalFile, _processFile, _processGenerator, _cur, _newProxy, _processDependents, _markFound } = symbols; | ||
@@ -229,2 +228,3 @@ class Defiler extends EventEmitter { | ||
dir, | ||
filter, | ||
read = true, | ||
@@ -239,4 +239,11 @@ enc = 'utf8', | ||
if (typeof dir !== 'string') throw new TypeError('defiler: dir must be a string') | ||
if (typeof read !== 'boolean') throw new TypeError('defiler: read must be a boolean') | ||
if (!Buffer.isEncoding(enc)) throw new TypeError('defiler: enc must be a supported encoding') | ||
if (typeof filter !== 'undefined' && 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 (typeof watch$$1 !== 'boolean') throw new TypeError('defiler: watch must be a boolean') | ||
@@ -253,20 +260,21 @@ if (typeof debounce !== 'number') throw new TypeError('defiler: debounce must be a number') | ||
} | ||
if (typeof resolver !== 'undefined' && typeof resolver !== 'function') { | ||
throw new TypeError('defiler: resolver must be a function') | ||
} | ||
super(); | ||
Object.assign(this, { | ||
paths: new Set(), // set of original paths for all physical files | ||
[_origData]: new Map(), // original paths -> original file data for all physical files ({ path, stats, bytes, enc }) | ||
files: new Map(), // original paths -> transformed files for all physical and virtual files | ||
[_status]: null, // null = exec not called; false = exec pending; true = exec finished | ||
[_watcher]: new Watcher({ dir: resolve(dir), read, enc, watch: watch$$1, debounce }), // Watcher instance | ||
[_transform]: transform, // the transform to run on all files | ||
[_generators]: new Map(generators.map(generator => [Symbol(), generator])), // unique symbols -> registered generators | ||
[_resolver]: resolver, // (base, path) => path resolver function, used in defiler.get and defiler.add from transform | ||
[_active]: new Set(), // original paths of all files currently undergoing transformation and symbols of all generators currently running | ||
[_waitingFor]: new Map(), // original paths -> number of other files they're currently waiting on to exist | ||
[_whenFound]: new Map(), // original paths -> { promise, resolve } objects for when awaited files become available | ||
[_cur]: { root: null, dep: null }, // (set via proxy) root: the current root dependent, for use in _dependencies; dep: the current immediate dependent, for use in _waitingFor | ||
[_dependencies]: new Map(), // original paths of dependents -> set of original paths of dependencies, specifying changes to which files should trigger re-processing which other files | ||
[_queue$1]: [], // queue of pending Watcher events to handle | ||
[_isProcessing$1]: false, // whether some Watcher event is currently already in the process of being handled | ||
}); | ||
this.paths = new Set(); // set of original paths for all physical files | ||
this[_origData] = new Map(); // original paths -> original file data for all physical files ({ path, stats, bytes, enc }) | ||
this.files = new Map(); // original paths -> transformed files for all physical and virtual files | ||
this[_status] = null; // null = exec not called; false = exec pending; true = exec finished | ||
this[_watcher] = new Watcher({ dir: resolve(dir), filter, read, enc, watch: watch$$1, debounce }); // Watcher instance | ||
this[_transform] = transform; // the transform to run on all files | ||
this[_generators] = new Map(generators.map(generator => [Symbol(), generator])); // unique symbols -> registered generators | ||
this[_resolver] = resolver; // (base, path) => path resolver function, used in defiler.get and defiler.add from transform | ||
this[_active] = new Set(); // original paths of all files currently undergoing transformation and symbols of all generators currently running | ||
this[_waitingFor] = new Map(); // original paths -> number of other files they're currently waiting on to exist | ||
this[_whenFound] = new Map(); // original paths -> { promise, resolve } objects for when awaited files become available | ||
this[_cur] = { root: null, parent: null }; // (set via proxy) root: the current root dependent, for use in _deps; parent: the current immediate dependent, for use in _waitingFor and the resolver | ||
this[_deps] = []; // array of [dependent, dependency] pairs, specifying changes to which files should trigger re-processing which other files | ||
this[_queue$1] = []; // queue of pending Watcher events to handle | ||
this[_isProcessing$1] = false; // whether some Watcher event is currently already in the process of being handled | ||
} | ||
@@ -302,19 +310,9 @@ | ||
async get(path) { | ||
if ( | ||
typeof path !== 'string' && | ||
(!Array.isArray(path) || path.some(path => typeof path !== 'string')) | ||
) { | ||
throw new TypeError('defiler.get: path must be a string or an array of strings') | ||
} | ||
if (Array.isArray(path)) return Promise.all(path.map(path => this.get(path))) | ||
let { [_cur]: cur, [_waitingFor]: waitingFor } = this; | ||
if (this[_resolver] && typeof cur.dep === 'string') { | ||
path = this[_resolver](cur.dep, path); | ||
} | ||
if (cur.root) { | ||
if (!this[_dependencies].has(cur.root)) this[_dependencies].set(cur.root, new Set()); | ||
this[_dependencies].get(cur.root).add(path); | ||
} | ||
if (this[_resolver] && typeof cur.parent === 'string') path = this[_resolver](cur.parent, path); | ||
if (typeof path !== 'string') throw new TypeError('defiler.get: path must be a string') | ||
if (cur.root) this[_deps].push([cur.root, path]); | ||
if (!this[_status] && !this.files.has(path)) { | ||
if (cur.dep) waitingFor.set(cur.dep, (waitingFor.get(cur.dep) || 0) + 1); | ||
if (cur.parent) waitingFor.set(cur.parent, (waitingFor.get(cur.parent) || 0) + 1); | ||
if (!this[_whenFound].has(path)) { | ||
@@ -325,3 +323,3 @@ let resolve$$1; | ||
await this[_whenFound].get(path).promise; | ||
if (cur.dep) waitingFor.set(cur.dep, waitingFor.get(cur.dep) - 1); | ||
if (cur.parent) waitingFor.set(cur.parent, waitingFor.get(cur.parent) - 1); | ||
} | ||
@@ -331,8 +329,8 @@ return this.files.get(path) | ||
// add a new non-physical file | ||
// add a new virtual file | ||
add(file) { | ||
if (this[_status] === null) throw new Error('defiler.add: cannot call before calling exec') | ||
if (typeof file !== 'object') throw new TypeError('defiler.add: file must be an object') | ||
if (this[_resolver] && typeof this[_cur].dep === 'string') { | ||
file.path = this[_resolver](this[_cur].dep, file.path); | ||
if (this[_resolver] && typeof this[_cur].parent === 'string') { | ||
file.path = this[_resolver](this[_cur].parent, file.path); | ||
} | ||
@@ -365,3 +363,3 @@ this[_processFile](file); | ||
this.emit('deleted', { defiler: this, file }); | ||
this[_processDependents](path); | ||
if (this[_status]) this[_processDependents](path); | ||
} | ||
@@ -376,4 +374,7 @@ await done; | ||
let { dir, read, enc } = this[_watcher]; | ||
let data = { path, stats, enc }; | ||
if (read) data.bytes = await readFile$1(dir + '/' + path); | ||
let data = { path, stats }; | ||
if (read && (typeof read !== 'function' || (await read({ path, stats })))) { | ||
data.bytes = await readFile$1(dir + '/' + path); | ||
} | ||
data.enc = typeof enc === 'function' ? await enc({ path, stats, bytes: data.bytes }) : enc; | ||
this.paths.add(path); | ||
@@ -386,10 +387,11 @@ this[_origData].set(path, data); | ||
// transform a file, store it, and process dependents | ||
async [_processFile](file) { | ||
file = Object.assign(new File(), file); | ||
async [_processFile](data) { | ||
let file = Object.assign(new File(), data); | ||
let { path } = file; | ||
this[_active].add(path); | ||
let defiler = this[_newProxy](path); | ||
try { | ||
await this[_transform]({ defiler: this[_newProxy](path), file }); | ||
await this[_transform]({ defiler, file }); | ||
} catch (error) { | ||
this.emit('error', { defiler: this, file, error }); | ||
this.emit('error', { defiler, file, error }); | ||
} | ||
@@ -399,3 +401,3 @@ this.files.set(path, file); | ||
this[_markFound](path); | ||
this[_processDependents](path); | ||
if (this[_status]) this[_processDependents](path); | ||
this[_active].delete(path); | ||
@@ -413,10 +415,4 @@ if (!this[_active].size) { | ||
[_processDependents](path) { | ||
if (!this[_status]) return | ||
let dependents = new Set(); | ||
for (let [dependent, dependencies] of this[_dependencies].entries()) { | ||
if (dependencies.has(path)) { | ||
dependents.add(dependent); | ||
this[_dependencies].delete(dependent); | ||
} | ||
} | ||
let dependents = new Set(this[_deps].map(([dependent, dep]) => dep === path && dependent)); | ||
this[_deps] = this[_deps].filter(([dependent]) => !dependents.has(dependent)); | ||
if (!dependents.size && !this[_active].size) this[_endWave](); | ||
@@ -436,6 +432,7 @@ for (let dependent of dependents) { | ||
let generator = this[_generators].get(symbol); | ||
let defiler = this[_newProxy](symbol); | ||
try { | ||
await generator({ defiler: this[_newProxy](symbol) }); | ||
await generator({ defiler }); | ||
} catch (error) { | ||
this.emit('error', { defiler: this, generator, error }); | ||
this.emit('error', { defiler, generator, error }); | ||
} | ||
@@ -445,5 +442,5 @@ this[_active].delete(symbol); | ||
// create a defiler Proxy for the given path, always overriding _cur.dep and only overriding _cur.root if it is not yet set | ||
// create a defiler Proxy for the given path, always overriding _cur.parent and only overriding _cur.root if it is not yet set | ||
[_newProxy](path) { | ||
let cur = { root: this[_cur].root || path, dep: path }; | ||
let cur = { root: this[_cur].root || path, parent: path }; | ||
return new Proxy(this, { get: (_, key) => (key === _cur ? cur : this[key]) }) | ||
@@ -450,0 +447,0 @@ } |
{ | ||
"name": "defiler", | ||
"version": "0.13.5", | ||
"version": "0.14.0", | ||
"description": "A small, strange building block", | ||
@@ -5,0 +5,0 @@ "keywords": ["build", "framework", "async", "watch"], |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
108885
801