Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

defiler

Package Overview
Dependencies
Maintainers
1
Versions
58
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

defiler - npm Package Compare versions

Comparing version 0.15.3 to 0.16.0

6

CHANGELOG.md

@@ -0,1 +1,7 @@

# v0.16.0
- Add `type` field to object passed to transform
- Add `onerror` handler callback option to `Defiler` constructor
- Removed emitted events from `Defiler` instance, as these are now handled more generally by `type` and `onerror`
# v0.15.3

@@ -2,0 +8,0 @@

507

dist/index.cjs.js

@@ -10,24 +10,38 @@ 'use strict';

var symbols = new Proxy({}, { get: (_, key) => Symbol(key) })
const _path = Symbol();
const _dir = Symbol();
const _filename = Symbol();
const _ext = Symbol();
const _enc = Symbol();
const _bytes = Symbol();
const _text = Symbol();
let { _path, _dir, _filename, _ext, _enc, _bytes, _text } = symbols;
class File {
constructor() {
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
// path of file
this[_path] = null;
// cached dir
this[_dir] = null;
// cached filename
this[_filename] = null;
// cached ext
this[_ext] = null;
// stats of file
this.stats = null;
// encoding
this[_enc] = 'utf8';
// Buffer of file contents
this[_bytes] = null;
// string of file contents
this[_text] = null;
}
get path() {
return this[_path]
return this[_path];
}
set path(path$$1) {
if (typeof path$$1 !== 'string') throw new TypeError('file.path must be a string')
if (typeof path$$1 !== 'string') {
throw new TypeError('file.path must be a string');
}
if (this[_path] !== path$$1) {

@@ -41,10 +55,12 @@ this[_path] = path$$1;

if (this[_dir] == null) {
let p = this[_path].lastIndexOf('/');
const p = this[_path].lastIndexOf('/');
this[_dir] = p > -1 ? this[_path].slice(0, p) : '';
}
return this[_dir]
return this[_dir];
}
set dir(dir) {
if (typeof dir !== 'string') throw new TypeError('file.dir must be a string')
if (typeof dir !== 'string') {
throw new TypeError('file.dir must be a string');
}
this.path = (dir ? dir + '/' : '') + this.filename;

@@ -55,12 +71,15 @@ }

if (this[_filename] == null) {
let p = this[_path].lastIndexOf('/');
const p = this[_path].lastIndexOf('/');
this[_filename] = p > -1 ? this[_path].slice(p + 1) : '';
}
return this[_filename]
return this[_filename];
}
set filename(filename) {
if (typeof filename !== 'string') throw new TypeError('file.filename must be a string')
let old = this.filename;
this.path = (old ? this[_path].slice(0, -old.length) : this[_path]) + filename;
if (typeof filename !== 'string') {
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;
}

@@ -70,12 +89,14 @@

if (this[_ext] == null) {
let p1 = this[_path].lastIndexOf('.');
let p2 = this[_path].lastIndexOf('/');
const p1 = this[_path].lastIndexOf('.');
const p2 = this[_path].lastIndexOf('/');
this[_ext] = p1 > -1 && p1 > p2 ? this[_path].slice(p1) : '';
}
return this[_ext]
return this[_ext];
}
set ext(ext) {
if (typeof ext !== 'string') throw new TypeError('file.ext must be a string')
let old = this.ext;
if (typeof ext !== 'string') {
throw new TypeError('file.ext must be a string');
}
const old = this.ext;
this.path = (old ? this[_path].slice(0, -old.length) : this[_path]) + ext;

@@ -85,7 +106,9 @@ }

get enc() {
return this[_enc]
return this[_enc];
}
set enc(enc) {
if (!Buffer.isEncoding(enc)) throw new TypeError('file.enc must be a supported encoding')
if (!Buffer.isEncoding(enc)) {
throw new TypeError('file.enc must be a supported encoding');
}
this[_enc] = enc;

@@ -97,3 +120,3 @@ }

? (this[_bytes] = Buffer.from(this[_text], this[_enc]))
: this[_bytes]
: this[_bytes];
}

@@ -103,3 +126,3 @@

if (bytes != null && !Buffer.isBuffer(bytes)) {
throw new TypeError('file.bytes must be a Buffer or null')
throw new TypeError('file.bytes must be a Buffer or null');
}

@@ -113,3 +136,3 @@ this[_bytes] = bytes;

? (this[_text] = this[_bytes].toString(this[_enc]))
: this[_text]
: this[_text];
}

@@ -119,3 +142,3 @@

if (text != null && typeof text !== 'string') {
throw new TypeError('file.text must be a string or null')
throw new TypeError('file.text must be a string or null');
}

@@ -131,3 +154,10 @@ this[_text] = text;

let { _watchers, _stats, _timeouts, _queue, _isProcessing, _recurse, _handle, _enqueue } = symbols;
const _watchers = Symbol();
const _stats = Symbol();
const _timeouts = Symbol();
const _queue = Symbol();
const _isProcessing = Symbol();
const _recurse = Symbol();
const _handle = Symbol();
const _enqueue = Symbol();

@@ -138,14 +168,22 @@ class Watcher extends EventEmitter {

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
// paths of all directories -> FSWatcher instances
this[_watchers] = new Map();
// paths of all files -> file stats
this[_stats] = new Map();
// paths of files with pending debounced events -> setTimeout timer ids
this[_timeouts] = new Map();
// queue of pending FSWatcher events to handle
this[_queue] = [];
// whether some FSWatcher event is currently already in the process of being handled
this[_isProcessing] = false;
}
// recurse directroy, get stats, set up FSWatcher instances
// recurse directory, get stats, set up FSWatcher instances
// returns array of { path, stats }
async init() {
await this[_recurse](this.dir);
return [...this[_stats].entries()].map(([path$$1, stats]) => ({ path: path$$1, stats }))
return [...this[_stats].entries()].map(([path$$1, stats]) => ({
path: path$$1,
stats,
}));
}

@@ -155,10 +193,16 @@

async [_recurse](full) {
let path$$1 = full.slice(this.dir.length + 1);
let stats = await stat(full);
if (this.filter && !await this.filter({ path: path$$1, stats })) return
const path$$1 = full.slice(this.dir.length + 1);
const stats = await stat(full);
if (this.filter && !await this.filter({ path: path$$1, stats })) {
return;
}
if (stats.isFile()) {
this[_stats].set(path$$1, stats);
} else if (stats.isDirectory()) {
if (this.watch) this[_watchers].set(path$$1, fs.watch(full, this[_handle].bind(this, full)));
await Promise.all((await readdir(full)).map(sub => this[_recurse](full + '/' + sub)));
if (this.watch) {
this[_watchers].set(path$$1, fs.watch(full, this[_handle].bind(this, full)));
}
await Promise.all(
(await readdir(full)).map(sub => this[_recurse](full + '/' + sub)),
);
}

@@ -169,3 +213,3 @@ }

[_handle](dir, event, file) {
let full = dir + '/' + file;
const full = dir + '/' + file;
if (this[_timeouts].has(full)) clearTimeout(this[_timeouts].get(full));

@@ -184,10 +228,14 @@ this[_timeouts].set(

this[_queue].push(full);
if (this[_isProcessing]) return
if (this[_isProcessing]) {
return;
}
this[_isProcessing] = true;
while (this[_queue].length) {
let full = this[_queue].shift();
let path$$1 = full.slice(this.dir.length + 1);
const full = this[_queue].shift();
const path$$1 = full.slice(this.dir.length + 1);
try {
let stats = await stat(full);
if (this.filter && !await this.filter({ path: path$$1, stats })) continue
const stats = await stat(full);
if (this.filter && !await this.filter({ path: path$$1, stats })) {
continue;
}
if (stats.isFile()) {

@@ -200,4 +248,6 @@ // note the new/changed file

await this[_recurse](full);
for (let [newPath, stats] of this[_stats].entries()) {
if (newPath.startsWith(path$$1 + '/')) this.emit('', { event: '+', path: newPath, stats });
for (const [newPath, stats] of this[_stats].entries()) {
if (newPath.startsWith(path$$1 + '/')) {
this.emit('', { event: '+', path: newPath, stats });
}
}

@@ -213,3 +263,3 @@ }

// note the deleted directory: stop watching it, and report any files that were in it
for (let old of this[_watchers].keys()) {
for (const old of this[_watchers].keys()) {
if (old === path$$1 || old.startsWith(path$$1 + '/')) {

@@ -220,3 +270,3 @@ this[_watchers].get(old).close();

}
for (let old of this[_stats].keys()) {
for (const old of this[_stats].keys()) {
if (old.startsWith(path$$1 + '/')) {

@@ -234,10 +284,36 @@ this[_stats].delete(old);

// prettier-ignore
let { _origData, _status, _watchers: _watchers$1, _transform, _generators, _resolver, _active, _waitingFor, _whenFound, _deps, _queue: _queue$1, _isProcessing: _isProcessing$1, _startWave, _endWave, _enqueue: _enqueue$1, _processPhysicalFile, _processFile, _processGenerator, _checkWave, _current, _newProxy, _processDependents, _markFound } = symbols;
const _origData = Symbol();
const _status = Symbol();
const _before = Symbol();
const _during = Symbol();
const _after = Symbol();
const _watchers$1 = Symbol();
const _transform = Symbol();
const _generators = Symbol();
const _resolver = Symbol();
const _onerror = Symbol();
const _active = Symbol();
const _waitingFor = Symbol();
const _whenFound = Symbol();
const _deps = Symbol();
const _queue$1 = Symbol();
const _isProcessing$1 = Symbol();
const _startWave = Symbol();
const _endWave = Symbol();
const _enqueue$1 = Symbol();
const _processPhysicalFile = Symbol();
const _processFile = Symbol();
const _callTransform = Symbol();
const _processGenerator = Symbol();
const _checkWave = Symbol();
const _current = Symbol();
const _newProxy = Symbol();
const _processDependents = Symbol();
const _markFound = Symbol();
class Defiler extends EventEmitter {
constructor(...dirs) {
let { transform, generators = [], resolver } = dirs.pop();
class Defiler {
constructor(...args) {
const { transform, generators = [], resolver, onerror } = args.pop();
if (typeof transform !== 'function') {
throw new TypeError('defiler: transform must be a function')
throw new TypeError('defiler: transform must be a function');
}

@@ -248,42 +324,87 @@ if (

) {
throw new TypeError('defiler: generators must be an array of functions')
throw new TypeError('defiler: generators must be an array of functions');
}
if (typeof resolver !== 'undefined' && typeof resolver !== 'function') {
throw new TypeError('defiler: resolver must be a function')
if (resolver && typeof resolver !== 'function') {
throw new TypeError('defiler: resolver must be a function');
}
super();
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[_watchers$1] = dirs.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 (typeof filter !== 'undefined' && typeof filter !== 'function') {
throw new TypeError('defiler: filter must be a function')
if (onerror && typeof onerror !== 'function') {
throw new TypeError('defiler: onerror must be a function');
}
// set of original paths for all physical files
this.paths = new Set();
// original paths -> original file data for all physical files ({ path, stats, bytes, enc })
this[_origData] = new Map();
// original paths -> transformed files for all physical and virtual files
this.files = new Map();
// _before, _during, or _after exec has been called
this[_status] = _before;
// Watcher instances
this[_watchers$1] = 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')
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')
throw new TypeError(
'defiler: enc must be a supported encoding or a function',
);
}
if (typeof pre !== 'undefined' && typeof pre !== 'function') {
throw new TypeError('defiler: pre must be 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 new Watcher({ dir: path.resolve(dir), filter, read, enc, pre, watch, debounce })
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 new Watcher({
dir: path.resolve(dir),
filter,
read,
enc,
pre,
watch,
debounce,
});
},
); // Watcher instances
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[_current] = null; // (set via proxy) the current immediate dependent (path or generator symbol), for use in _deps, _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
);
// the transform to run on all files
this[_transform] = transform;
// unique symbols -> registered generators
this[_generators] = new Map(
generators.map(generator => [Symbol(), generator]),
);
// (base, path) => path resolver function, used in defiler.get and defiler.add from transform
this[_resolver] = resolver;
// handler to call when errors occur
this[_onerror] = onerror;
// original paths of all files currently undergoing transformation and symbols of all generators currently running
this[_active] = new Set();
// original paths -> number of other files they're currently waiting on to exist
this[_waitingFor] = new Map();
// original paths -> { promise, resolve } objects for when awaited files become available
this[_whenFound] = new Map();
// (set via proxy) the current immediate dependent (path or generator symbol), for use in _deps, _waitingFor, and the resolver
this[_current] = null;
// array of [dependent, dependency] pairs, specifying changes to which files should trigger re-processing which other files
this[_deps] = [];
// queue of pending Watcher events to handle
this[_queue$1] = [];
// whether some Watcher event is currently already in the process of being handled
this[_isProcessing$1] = false;
}

@@ -293,8 +414,10 @@

async exec() {
if (this[_status] !== null) throw new Error('defiler.exec: cannot call more than once')
this[_status] = false;
if (this[_status] !== _before) {
throw new Error('defiler.exec: cannot call more than once');
}
this[_status] = _during;
this[_isProcessing$1] = true;
let done = this[_startWave]();
const done = this[_startWave]();
// init the Watcher instances
let files = [];
const files = [];
await Promise.all(

@@ -306,4 +429,6 @@ this[_watchers$1].map(async watcher => {

(await watcher.init()).map(async file => {
let { path: path$$1 } = file;
if (watcher.pre) await watcher.pre(file);
const { path: path$$1 } = file;
if (watcher.pre) {
await watcher.pre(file);
}
this.paths.add(file.path);

@@ -316,10 +441,16 @@ this[_active].add(file.path);

);
for (let symbol of this[_generators].keys()) this[_active].add(symbol);
for (const symbol of this[_generators].keys()) {
this[_active].add(symbol);
}
// process each physical file
for (let [watcher, path$$1, file] of files) this[_processPhysicalFile](watcher, path$$1, file);
for (const [watcher, path$$1, file] of files) {
this[_processPhysicalFile](watcher, path$$1, file);
}
// process each generator
for (let symbol of this[_generators].keys()) this[_processGenerator](symbol);
for (const symbol of this[_generators].keys()) {
this[_processGenerator](symbol);
}
// wait and finish up
await done;
this[_status] = true;
this[_status] = _after;
this[_isProcessing$1] = false;

@@ -331,17 +462,30 @@ this[_enqueue$1]();

async get(path$$1) {
if (Array.isArray(path$$1)) return Promise.all(path$$1.map(path$$1 => this.get(path$$1)))
let { [_current]: current, [_waitingFor]: waitingFor } = this;
if (Array.isArray(path$$1)) {
return Promise.all(path$$1.map(path$$1 => this.get(path$$1)));
}
const { [_current]: current, [_waitingFor]: waitingFor } = this;
path$$1 = this.resolve(path$$1);
if (typeof path$$1 !== 'string') throw new TypeError('defiler.get: path must be a string')
if (current) this[_deps].push([current, path$$1]);
if (!this[_status] && !this.files.has(path$$1)) {
if (current) waitingFor.set(current, (waitingFor.get(current) || 0) + 1);
if (typeof path$$1 !== 'string') {
throw new TypeError('defiler.get: path must be a string');
}
if (current) {
this[_deps].push([current, path$$1]);
}
if (this[_status] === _during && !this.files.has(path$$1)) {
if (current) {
waitingFor.set(current, (waitingFor.get(current) || 0) + 1);
}
if (!this[_whenFound].has(path$$1)) {
let resolve;
this[_whenFound].set(path$$1, { promise: new Promise(res => (resolve = res)), resolve });
this[_whenFound].set(path$$1, {
promise: new Promise(res => (resolve = res)),
resolve,
});
}
await this[_whenFound].get(path$$1).promise;
if (current) waitingFor.set(current, waitingFor.get(current) - 1);
if (current) {
waitingFor.set(current, waitingFor.get(current) - 1);
}
}
return this.files.get(path$$1)
return this.files.get(path$$1);
}

@@ -351,7 +495,11 @@

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[_status] === _before) {
throw new Error('defiler.add: cannot call before calling exec');
}
if (typeof file !== 'object') {
throw new TypeError('defiler.add: file must be an object');
}
file.path = this.resolve(file.path);
this[_origData].set(file.path, file);
this[_processFile](file);
this[_processFile](file, 'add');
}

@@ -363,3 +511,3 @@

? this[_resolver](this[_current], path$$1)
: path$$1
: path$$1;
}

@@ -371,3 +519,3 @@

[_startWave]() {
return new Promise(res => (this[_endWave] = res))
return new Promise(res => (this[_endWave] = res));
}

@@ -377,18 +525,25 @@

async [_enqueue$1](watcher, event) {
if (event) this[_queue$1].push([watcher, event]);
if (this[_isProcessing$1]) return
if (event) {
this[_queue$1].push([watcher, event]);
}
if (this[_isProcessing$1]) {
return;
}
this[_isProcessing$1] = true;
while (this[_queue$1].length) {
let done = this[_startWave]();
let [watcher, { event, path: path$$1, stats }] = this[_queue$1].shift();
let file = { path: path$$1, stats };
if (watcher.pre) await watcher.pre(file);
if (event === '+') this[_processPhysicalFile](watcher, path$$1, file);
else if (event === '-') {
let { path: path$$1 } = file;
file = this.files.get(path$$1);
const done = this[_startWave]();
const [watcher, { event, path: path$$1, stats }] = this[_queue$1].shift();
const file = { path: path$$1, stats };
if (watcher.pre) {
await watcher.pre(file);
}
if (event === '+') {
this[_processPhysicalFile](watcher, path$$1, file);
} else if (event === '-') {
const { path: path$$1 } = file;
const oldFile = this.files.get(path$$1);
this.paths.delete(path$$1);
this[_origData].delete(path$$1);
this.files.delete(path$$1);
this.emit('deleted', { defiler: this, file });
await this[_callTransform](oldFile, 'delete');
this[_processDependents](path$$1);

@@ -403,27 +558,28 @@ }

async [_processPhysicalFile]({ dir, read, enc }, path$$1, file) {
if (typeof read === 'function') read = await read({ path: path$$1, stats: file.stats });
if (read) file.bytes = await readFile(dir + '/' + path$$1);
if (typeof enc === 'function') enc = await enc({ path: path$$1, stats: file.stats, bytes: file.bytes });
if (typeof read === 'function') {
read = await read({ path: path$$1, stats: file.stats });
}
if (read) {
file.bytes = await readFile(dir + '/' + path$$1);
}
if (typeof enc === 'function') {
enc = await enc({ path: path$$1, stats: file.stats, bytes: file.bytes });
}
file.enc = enc;
this.paths.add(file.path);
this[_origData].set(file.path, file);
this.emit('read', { defiler: this, file });
await this[_processFile](file);
await this[_processFile](file, 'read');
}
// transform a file, store it, and process dependents
async [_processFile](data) {
let file = Object.assign(new File(), data);
let { path: path$$1 } = file;
async [_processFile](data, type) {
const file = Object.assign(new File(), data);
const { path: path$$1 } = file;
this[_active].add(path$$1);
let defiler = this[_newProxy](path$$1);
try {
await this[_transform]({ defiler, file });
} catch (error) {
this.emit('error', { defiler, file, error });
}
await this[_callTransform](file, type);
this.files.set(path$$1, file);
this.emit('file', { defiler: this, file });
this[_markFound](path$$1);
if (this[_status]) this[_processDependents](path$$1);
if (this[_status] === _after) {
this[_processDependents](path$$1);
}
this[_active].delete(path$$1);

@@ -433,11 +589,25 @@ this[_checkWave]();

// call the transform on a file with the given changed and deleted flags, and handle errors
async [_callTransform](file, type) {
let defiler = this[_newProxy](file.path);
try {
await this[_transform]({ defiler, file, type });
} catch (error) {
if (this[_onerror]) {
this[_onerror]({ defiler, file, type, error });
}
}
}
// run the generator given by the symbol
async [_processGenerator](symbol) {
this[_active].add(symbol);
let generator = this[_generators].get(symbol);
let defiler = this[_newProxy](symbol);
const generator = this[_generators].get(symbol);
const defiler = this[_newProxy](symbol);
try {
await generator({ defiler });
} catch (error) {
this.emit('error', { defiler, generator, error });
if (this[_onerror]) {
this[_onerror]({ defiler, generator, error });
}
}

@@ -450,10 +620,21 @@ this[_active].delete(symbol);

[_processDependents](path$$1) {
let dependents = new Set();
for (let [dependent, dep] of this[_deps]) if (dep === path$$1) dependents.add(dependent);
this[_deps] = this[_deps].filter(([dependent]) => !dependents.has(dependent));
if (!dependents.size && !this[_active].size) this[_endWave]();
for (let dependent of dependents) {
if (this[_origData].has(dependent)) this[_processFile](this[_origData].get(dependent));
else if (this[_generators].has(dependent)) this[_processGenerator](dependent);
const dependents = new Set();
for (const [dependent, dep] of this[_deps]) {
if (dep === path$$1) {
dependents.add(dependent);
}
}
this[_deps] = this[_deps].filter(
([dependent]) => !dependents.has(dependent),
);
if (!dependents.size && !this[_active].size) {
this[_endWave]();
}
for (const dependent of dependents) {
if (this[_origData].has(dependent)) {
this[_processFile](this[_origData].get(dependent), 'retransform');
} else if (this[_generators].has(dependent)) {
this[_processGenerator](dependent);
}
}
}

@@ -463,7 +644,15 @@

[_checkWave]() {
if (!this[_active].size) this[_endWave]();
else if (!this[_status] && [...this[_active]].every(path$$1 => this[_waitingFor].get(path$$1))) {
if (!this[_active].size) {
this[_endWave]();
} else if (
this[_status] === _during &&
[...this[_active]].every(path$$1 => this[_waitingFor].get(path$$1))
) {
// all pending files are currently waiting for one or more other files to exist
// break deadlock: assume all files that have not appeared yet will never do so
for (let path$$1 of this[_whenFound].keys()) if (!this[_active].has(path$$1)) this[_markFound](path$$1);
for (const path$$1 of this[_whenFound].keys()) {
if (!this[_active].has(path$$1)) {
this[_markFound](path$$1);
}
}
}

@@ -474,3 +663,5 @@ }

[_newProxy](path$$1) {
return new Proxy(this, { get: (_, key) => (key === _current ? path$$1 : this[key]) })
return new Proxy(this, {
get: (_, key) => (key === _current ? path$$1 : this[key]),
});
}

@@ -480,3 +671,3 @@

[_markFound](path$$1) {
if (!this[_status] && this[_whenFound].has(path$$1)) {
if (this[_status] === _during && this[_whenFound].has(path$$1)) {
this[_whenFound].get(path$$1).resolve();

@@ -483,0 +674,0 @@ this[_whenFound].delete(path$$1);

@@ -6,24 +6,38 @@ import { readdir, readFile, stat, watch } from 'fs';

var symbols = new Proxy({}, { get: (_, key) => Symbol(key) })
const _path = Symbol();
const _dir = Symbol();
const _filename = Symbol();
const _ext = Symbol();
const _enc = Symbol();
const _bytes = Symbol();
const _text = Symbol();
let { _path, _dir, _filename, _ext, _enc, _bytes, _text } = symbols;
class File {
constructor() {
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
// path of file
this[_path] = null;
// cached dir
this[_dir] = null;
// cached filename
this[_filename] = null;
// cached ext
this[_ext] = null;
// stats of file
this.stats = null;
// encoding
this[_enc] = 'utf8';
// Buffer of file contents
this[_bytes] = null;
// string of file contents
this[_text] = null;
}
get path() {
return this[_path]
return this[_path];
}
set path(path) {
if (typeof path !== 'string') throw new TypeError('file.path must be a string')
if (typeof path !== 'string') {
throw new TypeError('file.path must be a string');
}
if (this[_path] !== path) {

@@ -37,10 +51,12 @@ this[_path] = path;

if (this[_dir] == null) {
let p = this[_path].lastIndexOf('/');
const p = this[_path].lastIndexOf('/');
this[_dir] = p > -1 ? this[_path].slice(0, p) : '';
}
return this[_dir]
return this[_dir];
}
set dir(dir) {
if (typeof dir !== 'string') throw new TypeError('file.dir must be a string')
if (typeof dir !== 'string') {
throw new TypeError('file.dir must be a string');
}
this.path = (dir ? dir + '/' : '') + this.filename;

@@ -51,12 +67,15 @@ }

if (this[_filename] == null) {
let p = this[_path].lastIndexOf('/');
const p = this[_path].lastIndexOf('/');
this[_filename] = p > -1 ? this[_path].slice(p + 1) : '';
}
return this[_filename]
return this[_filename];
}
set filename(filename) {
if (typeof filename !== 'string') throw new TypeError('file.filename must be a string')
let old = this.filename;
this.path = (old ? this[_path].slice(0, -old.length) : this[_path]) + filename;
if (typeof filename !== 'string') {
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;
}

@@ -66,12 +85,14 @@

if (this[_ext] == null) {
let p1 = this[_path].lastIndexOf('.');
let p2 = this[_path].lastIndexOf('/');
const p1 = this[_path].lastIndexOf('.');
const p2 = this[_path].lastIndexOf('/');
this[_ext] = p1 > -1 && p1 > p2 ? this[_path].slice(p1) : '';
}
return this[_ext]
return this[_ext];
}
set ext(ext) {
if (typeof ext !== 'string') throw new TypeError('file.ext must be a string')
let old = this.ext;
if (typeof ext !== 'string') {
throw new TypeError('file.ext must be a string');
}
const old = this.ext;
this.path = (old ? this[_path].slice(0, -old.length) : this[_path]) + ext;

@@ -81,7 +102,9 @@ }

get enc() {
return this[_enc]
return this[_enc];
}
set enc(enc) {
if (!Buffer.isEncoding(enc)) throw new TypeError('file.enc must be a supported encoding')
if (!Buffer.isEncoding(enc)) {
throw new TypeError('file.enc must be a supported encoding');
}
this[_enc] = enc;

@@ -93,3 +116,3 @@ }

? (this[_bytes] = Buffer.from(this[_text], this[_enc]))
: this[_bytes]
: this[_bytes];
}

@@ -99,3 +122,3 @@

if (bytes != null && !Buffer.isBuffer(bytes)) {
throw new TypeError('file.bytes must be a Buffer or null')
throw new TypeError('file.bytes must be a Buffer or null');
}

@@ -109,3 +132,3 @@ this[_bytes] = bytes;

? (this[_text] = this[_bytes].toString(this[_enc]))
: this[_text]
: this[_text];
}

@@ -115,3 +138,3 @@

if (text != null && typeof text !== 'string') {
throw new TypeError('file.text must be a string or null')
throw new TypeError('file.text must be a string or null');
}

@@ -127,3 +150,10 @@ this[_text] = text;

let { _watchers, _stats, _timeouts, _queue, _isProcessing, _recurse, _handle, _enqueue } = symbols;
const _watchers = Symbol();
const _stats = Symbol();
const _timeouts = Symbol();
const _queue = Symbol();
const _isProcessing = Symbol();
const _recurse = Symbol();
const _handle = Symbol();
const _enqueue = Symbol();

@@ -134,14 +164,22 @@ class Watcher extends EventEmitter {

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
// paths of all directories -> FSWatcher instances
this[_watchers] = new Map();
// paths of all files -> file stats
this[_stats] = new Map();
// paths of files with pending debounced events -> setTimeout timer ids
this[_timeouts] = new Map();
// queue of pending FSWatcher events to handle
this[_queue] = [];
// whether some FSWatcher event is currently already in the process of being handled
this[_isProcessing] = false;
}
// recurse directroy, get stats, set up FSWatcher instances
// recurse directory, get stats, set up FSWatcher instances
// returns array of { path, stats }
async init() {
await this[_recurse](this.dir);
return [...this[_stats].entries()].map(([path, stats]) => ({ path, stats }))
return [...this[_stats].entries()].map(([path, stats]) => ({
path,
stats,
}));
}

@@ -151,10 +189,16 @@

async [_recurse](full) {
let path = full.slice(this.dir.length + 1);
let stats = await stat$1(full);
if (this.filter && !await this.filter({ path, stats })) return
const path = full.slice(this.dir.length + 1);
const stats = await stat$1(full);
if (this.filter && !await this.filter({ path, stats })) {
return;
}
if (stats.isFile()) {
this[_stats].set(path, stats);
} else if (stats.isDirectory()) {
if (this.watch) this[_watchers].set(path, watch(full, this[_handle].bind(this, full)));
await Promise.all((await readdir$1(full)).map(sub => this[_recurse](full + '/' + sub)));
if (this.watch) {
this[_watchers].set(path, watch(full, this[_handle].bind(this, full)));
}
await Promise.all(
(await readdir$1(full)).map(sub => this[_recurse](full + '/' + sub)),
);
}

@@ -165,3 +209,3 @@ }

[_handle](dir, event, file) {
let full = dir + '/' + file;
const full = dir + '/' + file;
if (this[_timeouts].has(full)) clearTimeout(this[_timeouts].get(full));

@@ -180,10 +224,14 @@ this[_timeouts].set(

this[_queue].push(full);
if (this[_isProcessing]) return
if (this[_isProcessing]) {
return;
}
this[_isProcessing] = true;
while (this[_queue].length) {
let full = this[_queue].shift();
let path = full.slice(this.dir.length + 1);
const full = this[_queue].shift();
const path = full.slice(this.dir.length + 1);
try {
let stats = await stat$1(full);
if (this.filter && !await this.filter({ path, stats })) continue
const stats = await stat$1(full);
if (this.filter && !await this.filter({ path, stats })) {
continue;
}
if (stats.isFile()) {

@@ -196,4 +244,6 @@ // note the new/changed file

await this[_recurse](full);
for (let [newPath, stats] of this[_stats].entries()) {
if (newPath.startsWith(path + '/')) this.emit('', { event: '+', path: newPath, stats });
for (const [newPath, stats] of this[_stats].entries()) {
if (newPath.startsWith(path + '/')) {
this.emit('', { event: '+', path: newPath, stats });
}
}

@@ -209,3 +259,3 @@ }

// note the deleted directory: stop watching it, and report any files that were in it
for (let old of this[_watchers].keys()) {
for (const old of this[_watchers].keys()) {
if (old === path || old.startsWith(path + '/')) {

@@ -216,3 +266,3 @@ this[_watchers].get(old).close();

}
for (let old of this[_stats].keys()) {
for (const old of this[_stats].keys()) {
if (old.startsWith(path + '/')) {

@@ -230,10 +280,36 @@ this[_stats].delete(old);

// prettier-ignore
let { _origData, _status, _watchers: _watchers$1, _transform, _generators, _resolver, _active, _waitingFor, _whenFound, _deps, _queue: _queue$1, _isProcessing: _isProcessing$1, _startWave, _endWave, _enqueue: _enqueue$1, _processPhysicalFile, _processFile, _processGenerator, _checkWave, _current, _newProxy, _processDependents, _markFound } = symbols;
const _origData = Symbol();
const _status = Symbol();
const _before = Symbol();
const _during = Symbol();
const _after = Symbol();
const _watchers$1 = Symbol();
const _transform = Symbol();
const _generators = Symbol();
const _resolver = Symbol();
const _onerror = Symbol();
const _active = Symbol();
const _waitingFor = Symbol();
const _whenFound = Symbol();
const _deps = Symbol();
const _queue$1 = Symbol();
const _isProcessing$1 = Symbol();
const _startWave = Symbol();
const _endWave = Symbol();
const _enqueue$1 = Symbol();
const _processPhysicalFile = Symbol();
const _processFile = Symbol();
const _callTransform = Symbol();
const _processGenerator = Symbol();
const _checkWave = Symbol();
const _current = Symbol();
const _newProxy = Symbol();
const _processDependents = Symbol();
const _markFound = Symbol();
class Defiler extends EventEmitter {
constructor(...dirs) {
let { transform, generators = [], resolver } = dirs.pop();
class Defiler {
constructor(...args) {
const { transform, generators = [], resolver, onerror } = args.pop();
if (typeof transform !== 'function') {
throw new TypeError('defiler: transform must be a function')
throw new TypeError('defiler: transform must be a function');
}

@@ -244,42 +320,87 @@ if (

) {
throw new TypeError('defiler: generators must be an array of functions')
throw new TypeError('defiler: generators must be an array of functions');
}
if (typeof resolver !== 'undefined' && typeof resolver !== 'function') {
throw new TypeError('defiler: resolver must be a function')
if (resolver && typeof resolver !== 'function') {
throw new TypeError('defiler: resolver must be a function');
}
super();
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[_watchers$1] = dirs.map(
({ dir, filter, read = true, enc = 'utf8', pre, watch: watch$$1 = true, debounce = 10 }) => {
if (typeof dir !== 'string') throw new TypeError('defiler: dir must be a string')
if (typeof filter !== 'undefined' && typeof filter !== 'function') {
throw new TypeError('defiler: filter must be a function')
if (onerror && typeof onerror !== 'function') {
throw new TypeError('defiler: onerror must be a function');
}
// set of original paths for all physical files
this.paths = new Set();
// original paths -> original file data for all physical files ({ path, stats, bytes, enc })
this[_origData] = new Map();
// original paths -> transformed files for all physical and virtual files
this.files = new Map();
// _before, _during, or _after exec has been called
this[_status] = _before;
// Watcher instances
this[_watchers$1] = args.map(
({
dir,
filter,
read = true,
enc = 'utf8',
pre,
watch$$1 = 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')
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')
throw new TypeError(
'defiler: enc must be a supported encoding or a function',
);
}
if (typeof pre !== 'undefined' && typeof pre !== 'function') {
throw new TypeError('defiler: pre must be a function')
if (pre && typeof pre !== 'function') {
throw new TypeError('defiler: pre must be a function');
}
if (typeof watch$$1 !== 'boolean') throw new TypeError('defiler: watch must be a boolean')
if (typeof debounce !== 'number') throw new TypeError('defiler: debounce must be a number')
return new Watcher({ dir: resolve(dir), filter, read, enc, pre, watch: watch$$1, debounce })
if (typeof watch$$1 !== 'boolean') {
throw new TypeError('defiler: watch must be a boolean');
}
if (typeof debounce !== 'number') {
throw new TypeError('defiler: debounce must be a number');
}
return new Watcher({
dir: resolve(dir),
filter,
read,
enc,
pre,
watch: watch$$1,
debounce,
});
},
); // Watcher instances
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[_current] = null; // (set via proxy) the current immediate dependent (path or generator symbol), for use in _deps, _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
);
// the transform to run on all files
this[_transform] = transform;
// unique symbols -> registered generators
this[_generators] = new Map(
generators.map(generator => [Symbol(), generator]),
);
// (base, path) => path resolver function, used in defiler.get and defiler.add from transform
this[_resolver] = resolver;
// handler to call when errors occur
this[_onerror] = onerror;
// original paths of all files currently undergoing transformation and symbols of all generators currently running
this[_active] = new Set();
// original paths -> number of other files they're currently waiting on to exist
this[_waitingFor] = new Map();
// original paths -> { promise, resolve } objects for when awaited files become available
this[_whenFound] = new Map();
// (set via proxy) the current immediate dependent (path or generator symbol), for use in _deps, _waitingFor, and the resolver
this[_current] = null;
// array of [dependent, dependency] pairs, specifying changes to which files should trigger re-processing which other files
this[_deps] = [];
// queue of pending Watcher events to handle
this[_queue$1] = [];
// whether some Watcher event is currently already in the process of being handled
this[_isProcessing$1] = false;
}

@@ -289,8 +410,10 @@

async exec() {
if (this[_status] !== null) throw new Error('defiler.exec: cannot call more than once')
this[_status] = false;
if (this[_status] !== _before) {
throw new Error('defiler.exec: cannot call more than once');
}
this[_status] = _during;
this[_isProcessing$1] = true;
let done = this[_startWave]();
const done = this[_startWave]();
// init the Watcher instances
let files = [];
const files = [];
await Promise.all(

@@ -302,4 +425,6 @@ this[_watchers$1].map(async watcher => {

(await watcher.init()).map(async file => {
let { path } = file;
if (watcher.pre) await watcher.pre(file);
const { path } = file;
if (watcher.pre) {
await watcher.pre(file);
}
this.paths.add(file.path);

@@ -312,10 +437,16 @@ this[_active].add(file.path);

);
for (let symbol of this[_generators].keys()) this[_active].add(symbol);
for (const symbol of this[_generators].keys()) {
this[_active].add(symbol);
}
// process each physical file
for (let [watcher, path, file] of files) this[_processPhysicalFile](watcher, path, file);
for (const [watcher, path, file] of files) {
this[_processPhysicalFile](watcher, path, file);
}
// process each generator
for (let symbol of this[_generators].keys()) this[_processGenerator](symbol);
for (const symbol of this[_generators].keys()) {
this[_processGenerator](symbol);
}
// wait and finish up
await done;
this[_status] = true;
this[_status] = _after;
this[_isProcessing$1] = false;

@@ -327,17 +458,30 @@ this[_enqueue$1]();

async get(path) {
if (Array.isArray(path)) return Promise.all(path.map(path => this.get(path)))
let { [_current]: current, [_waitingFor]: waitingFor } = this;
if (Array.isArray(path)) {
return Promise.all(path.map(path => this.get(path)));
}
const { [_current]: current, [_waitingFor]: waitingFor } = this;
path = this.resolve(path);
if (typeof path !== 'string') throw new TypeError('defiler.get: path must be a string')
if (current) this[_deps].push([current, path]);
if (!this[_status] && !this.files.has(path)) {
if (current) waitingFor.set(current, (waitingFor.get(current) || 0) + 1);
if (typeof path !== 'string') {
throw new TypeError('defiler.get: path must be a string');
}
if (current) {
this[_deps].push([current, path]);
}
if (this[_status] === _during && !this.files.has(path)) {
if (current) {
waitingFor.set(current, (waitingFor.get(current) || 0) + 1);
}
if (!this[_whenFound].has(path)) {
let resolve$$1;
this[_whenFound].set(path, { promise: new Promise(res => (resolve$$1 = res)), resolve: resolve$$1 });
this[_whenFound].set(path, {
promise: new Promise(res => (resolve$$1 = res)),
resolve: resolve$$1,
});
}
await this[_whenFound].get(path).promise;
if (current) waitingFor.set(current, waitingFor.get(current) - 1);
if (current) {
waitingFor.set(current, waitingFor.get(current) - 1);
}
}
return this.files.get(path)
return this.files.get(path);
}

@@ -347,7 +491,11 @@

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[_status] === _before) {
throw new Error('defiler.add: cannot call before calling exec');
}
if (typeof file !== 'object') {
throw new TypeError('defiler.add: file must be an object');
}
file.path = this.resolve(file.path);
this[_origData].set(file.path, file);
this[_processFile](file);
this[_processFile](file, 'add');
}

@@ -359,3 +507,3 @@

? this[_resolver](this[_current], path)
: path
: path;
}

@@ -367,3 +515,3 @@

[_startWave]() {
return new Promise(res => (this[_endWave] = res))
return new Promise(res => (this[_endWave] = res));
}

@@ -373,18 +521,25 @@

async [_enqueue$1](watcher, event) {
if (event) this[_queue$1].push([watcher, event]);
if (this[_isProcessing$1]) return
if (event) {
this[_queue$1].push([watcher, event]);
}
if (this[_isProcessing$1]) {
return;
}
this[_isProcessing$1] = true;
while (this[_queue$1].length) {
let done = this[_startWave]();
let [watcher, { event, path, stats }] = this[_queue$1].shift();
let file = { path, stats };
if (watcher.pre) await watcher.pre(file);
if (event === '+') this[_processPhysicalFile](watcher, path, file);
else if (event === '-') {
let { path } = file;
file = this.files.get(path);
const done = this[_startWave]();
const [watcher, { event, path, stats }] = this[_queue$1].shift();
const file = { path, stats };
if (watcher.pre) {
await watcher.pre(file);
}
if (event === '+') {
this[_processPhysicalFile](watcher, path, file);
} else if (event === '-') {
const { path } = file;
const oldFile = this.files.get(path);
this.paths.delete(path);
this[_origData].delete(path);
this.files.delete(path);
this.emit('deleted', { defiler: this, file });
await this[_callTransform](oldFile, 'delete');
this[_processDependents](path);

@@ -399,27 +554,28 @@ }

async [_processPhysicalFile]({ dir, read, enc }, path, file) {
if (typeof read === 'function') read = await read({ path, stats: file.stats });
if (read) file.bytes = await readFile$1(dir + '/' + path);
if (typeof enc === 'function') enc = await enc({ path, stats: file.stats, bytes: file.bytes });
if (typeof read === 'function') {
read = await read({ path, stats: file.stats });
}
if (read) {
file.bytes = await readFile$1(dir + '/' + path);
}
if (typeof enc === 'function') {
enc = await enc({ path, stats: file.stats, bytes: file.bytes });
}
file.enc = enc;
this.paths.add(file.path);
this[_origData].set(file.path, file);
this.emit('read', { defiler: this, file });
await this[_processFile](file);
await this[_processFile](file, 'read');
}
// transform a file, store it, and process dependents
async [_processFile](data) {
let file = Object.assign(new File(), data);
let { path } = file;
async [_processFile](data, type) {
const file = Object.assign(new File(), data);
const { path } = file;
this[_active].add(path);
let defiler = this[_newProxy](path);
try {
await this[_transform]({ defiler, file });
} catch (error) {
this.emit('error', { defiler, file, error });
}
await this[_callTransform](file, type);
this.files.set(path, file);
this.emit('file', { defiler: this, file });
this[_markFound](path);
if (this[_status]) this[_processDependents](path);
if (this[_status] === _after) {
this[_processDependents](path);
}
this[_active].delete(path);

@@ -429,11 +585,25 @@ this[_checkWave]();

// call the transform on a file with the given changed and deleted flags, and handle errors
async [_callTransform](file, type) {
let defiler = this[_newProxy](file.path);
try {
await this[_transform]({ defiler, file, type });
} catch (error) {
if (this[_onerror]) {
this[_onerror]({ defiler, file, type, error });
}
}
}
// run the generator given by the symbol
async [_processGenerator](symbol) {
this[_active].add(symbol);
let generator = this[_generators].get(symbol);
let defiler = this[_newProxy](symbol);
const generator = this[_generators].get(symbol);
const defiler = this[_newProxy](symbol);
try {
await generator({ defiler });
} catch (error) {
this.emit('error', { defiler, generator, error });
if (this[_onerror]) {
this[_onerror]({ defiler, generator, error });
}
}

@@ -446,10 +616,21 @@ this[_active].delete(symbol);

[_processDependents](path) {
let dependents = new Set();
for (let [dependent, dep] of this[_deps]) if (dep === path) dependents.add(dependent);
this[_deps] = this[_deps].filter(([dependent]) => !dependents.has(dependent));
if (!dependents.size && !this[_active].size) this[_endWave]();
for (let dependent of dependents) {
if (this[_origData].has(dependent)) this[_processFile](this[_origData].get(dependent));
else if (this[_generators].has(dependent)) this[_processGenerator](dependent);
const dependents = new Set();
for (const [dependent, dep] of this[_deps]) {
if (dep === path) {
dependents.add(dependent);
}
}
this[_deps] = this[_deps].filter(
([dependent]) => !dependents.has(dependent),
);
if (!dependents.size && !this[_active].size) {
this[_endWave]();
}
for (const dependent of dependents) {
if (this[_origData].has(dependent)) {
this[_processFile](this[_origData].get(dependent), 'retransform');
} else if (this[_generators].has(dependent)) {
this[_processGenerator](dependent);
}
}
}

@@ -459,7 +640,15 @@

[_checkWave]() {
if (!this[_active].size) this[_endWave]();
else if (!this[_status] && [...this[_active]].every(path => this[_waitingFor].get(path))) {
if (!this[_active].size) {
this[_endWave]();
} else if (
this[_status] === _during &&
[...this[_active]].every(path => this[_waitingFor].get(path))
) {
// all pending files are currently waiting for one or more other files to exist
// break deadlock: assume all files that have not appeared yet will never do so
for (let path of this[_whenFound].keys()) if (!this[_active].has(path)) this[_markFound](path);
for (const path of this[_whenFound].keys()) {
if (!this[_active].has(path)) {
this[_markFound](path);
}
}
}

@@ -470,3 +659,5 @@ }

[_newProxy](path) {
return new Proxy(this, { get: (_, key) => (key === _current ? path : this[key]) })
return new Proxy(this, {
get: (_, key) => (key === _current ? path : this[key]),
});
}

@@ -476,3 +667,3 @@

[_markFound](path) {
if (!this[_status] && this[_whenFound].has(path)) {
if (this[_status] === _during && this[_whenFound].has(path)) {
this[_whenFound].get(path).resolve();

@@ -479,0 +670,0 @@ this[_whenFound].delete(path);

{
"name": "defiler",
"version": "0.15.3",
"version": "0.16.0",
"description": "A small, strange building block",
"keywords": ["build", "framework", "async", "watch"],
"keywords": [
"build",
"framework",
"async",
"watch"
],
"main": "./dist/index.cjs.js",
"module": "./dist/index.es.js",
"files": ["dist"],
"files": [
"dist"
],
"engines": {

@@ -21,3 +28,9 @@ "node": ">=8"

},
"homepage": "https://cndtr.io/defiler/"
"homepage": "https://cndtr.io/defiler/",
"devDependencies": {
"rollup": "*"
},
"scripts": {
"build": "rollup -c"
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc