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.12.1 to 0.13.0

8

CHANGELOG.md

@@ -0,1 +1,9 @@

# v0.13.0
- Remove concept of '`get` function' passed to transform and generators
- Add `defiler.get` method to replace it
- Fix a tricky dependency bug: If file or generator A added a virtual file B whose transformation depended on file C, make changing file C reprocess A, not B
- Remove `defiler.depend`, which was only exposed as a partial workaround for the above bug
- Remove non-useful `path` argument to `File` constructor
# v0.12.1

@@ -2,0 +10,0 @@

228

dist/index.cjs.js

@@ -17,18 +17,14 @@ 'use strict';

class File {
constructor(path$$1 = '') {
if (typeof path$$1 !== 'string') throw new TypeError('file.path must be a string')
// path of file
this[_path] = path$$1;
// cached dir/filename/ext values
this[_dir] = this[_filename] = this[_ext] = null;
// all historical paths of file
this.paths = path$$1 ? [path$$1] : [];
// stats of file
this.stats = null;
// encoding
this[_enc] = 'utf8';
// Buffer of file contents
this[_bytes] = null;
// string of file contents
this[_text] = null;
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
});
}

@@ -132,9 +128,9 @@

class Waiter {
// initialize/reset, and set a promise property that can be awaited
// initialize/reset, and return a promise that can be awaited
init() {
this[_count] = 0;
this.promise = new Promise((res, rej) => {
return new Promise((res, rej) => {
this[_resolve] = res;
this[_reject] = rej;
});
})
}

@@ -167,22 +163,16 @@

super();
// directory to recursively watch the contents of
this[_dir$1] = dir;
// whether to actually watch for changes (or just walk and retrieve contents and file stats)
this[_watch] = watch;
// fs.watch event debounce, in milliseconds
this[_debounce] = debounce;
// paths of all (recursive) directories -> FSWatcher instances
this[_dirs] = new Map();
// paths of all (recursive) files -> file stats
this[_files] = new Map();
// paths of (recursive) 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[_processing] = false;
Object.assign(this, {
[_dir$1]: dir, // directory to recursively watch the contents of
[_watch]: watch, // whether to actually watch for changes (or just walk and retrieve contents and file stats)
[_debounce]: debounce, // fs.watch event debounce, in milliseconds
[_dirs]: new Map(), // paths of all (recursive) directories -> FSWatcher instances
[_files]: 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
[_processing]: false, // whether some FSWatcher event is currently already in the process of being handled
});
}
// recurse directroy, get stats, set up FSWatcher instances
// returns array of { file, stats }
// returns array of { path, stats }
async init() {

@@ -286,3 +276,5 @@ await this[_recurse](this[_dir$1]);

_processGenerator,
_get,
_root,
_dependent,
_sub,
_processDependents,

@@ -311,42 +303,30 @@ _found,

if (
!generators[Symbol.iterator] ||
[...generators].some(generator => typeof generator !== 'function')
!Array.isArray(generators) ||
generators.some(generator => typeof generator !== 'function')
) {
throw new TypeError('defiler: generators must be a collection of functions')
throw new TypeError('defiler: generators must be an array of functions')
}
super();
// set of original paths for all physical files
this.paths = new Set();
// original paths -> original files for all physical files
this[_origFiles] = new Map();
// original paths -> transformed files for all physical and virtual files
this.files = new Map();
// null = exec not called; false = exec pending; true = exec finished
this[_status] = null;
// information about the directory to watch
dir = path.resolve(dir);
this[_dir$2] = { watcher: new Watcher(dir, watch, debounce), dir, read, enc, watch };
// the transform to run on all files
this[_transform] = transform;
// unique symbols -> registered generators
this[_generators] = new Map();
for (let generator of generators) this[_generators].set(Symbol(), generator);
// Waiter instance, to help wait for all promises in the current wave to resolve
this[_waiter] = new Waiter();
// original paths of all files currently undergoing transformation and symbols of all generators running
this[_pending] = new Set();
// original paths -> number of other files they're currently waiting on to exist
this[_waiting] = new Map();
// original paths -> { promise, resolve } objects for when awaited files become available
this[_available] = new Map();
// original paths of dependents -> set of original paths of dependencies, specifying changes to which files should trigger re-processing which other files
this[_dependents] = new Map();
// queue of pending Watcher events to handle
this[_queue$1] = [];
// whether some Watcher event is currently already in the process of being handled
this[_processing$1] = false;
Object.assign(this, {
paths: new Set(), // set of original paths for all physical files
[_origFiles]: new Map(), // original paths -> original file data for all physical files
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
[_dir$2]: { watcher: new Watcher(dir, watch, debounce), dir, read, enc, watch }, // information about the directory to watch
[_transform]: transform, // the transform to run on all files
[_generators]: new Map(generators.map(generator => [Symbol(), generator])), // unique symbols -> registered generators
[_waiter]: new Waiter(), // Waiter instance, to help wait for all promises in the current wave to resolve
[_pending]: new Set(), // original paths of all files currently undergoing transformation and symbols of all generators running
[_waiting]: new Map(), // original paths -> number of other files they're currently waiting on to exist
[_available]: new Map(), // original paths -> { promise, resolve } objects for when awaited files become available
[_root]: null, // (via proxy) the root dependent, for use in _dependents
[_dependent]: null, // (via proxy) the immediate dependent, for use in _waiting
[_dependents]: 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
[_processing$1]: false, // whether some Watcher event is currently already in the process of being handled
});
}
// exec
// execute everything, and return a promise that resolves when the first wave of processing is complete
async exec() {

@@ -356,3 +336,3 @@ if (this[_status] !== null) throw new Error('defiler.exec: cannot call more than once')

this[_processing$1] = true;
this[_waiter].init();
let done = this[_waiter].init();
// init the Watcher instance

@@ -373,3 +353,3 @@ let { watcher, watch } = this[_dir$2];

// wait and finish up
await this[_waiter].promise;
await done;
this[_status] = true;

@@ -379,3 +359,35 @@ this[_processing$1] = false;

// post-exec methods
// wait for a file to be available and retrieve it, marking dependencies as appropriate
async get(path$$1) {
if (
typeof path$$1 !== 'string' &&
(!Array.isArray(path$$1) || path$$1.some(path$$1 => typeof path$$1 !== 'string'))
) {
}
if (Array.isArray(path$$1)) return Promise.all(path$$1.map(path$$1 => this.get(path$$1)))
if (this[_root]) {
if (this[_dependents].has(this[_root])) {
this[_dependents].get(this[_root]).add(path$$1);
} else {
this[_dependents].set(this[_root], new Set([path$$1]));
}
}
if (!this[_status] && !this.files.has(path$$1)) {
if (this[_dependent]) {
this[_waiting].set(this[_dependent], (this[_waiting].get(this[_dependent]) || 0) + 1);
}
if (this[_available].has(path$$1)) {
await this[_available].get(path$$1).promise;
} else {
let resolve;
let promise = new Promise(res => (resolve = res));
this[_available].set(path$$1, { promise, resolve });
await promise;
}
if (this[_dependent]) {
this[_waiting].set(this[_dependent], this[_waiting].get(this[_dependent]) - 1);
}
}
return this.files.get(path$$1)
}

@@ -395,16 +407,2 @@ // add a new non-physical file

// mark dependence of one file on another
depend(dependent, path$$1) {
if (this[_status] === null) throw new Error('defiler.depend: cannot call before calling exec')
if (typeof dependent !== 'string' && !this[_generators].has(dependent)) {
throw new TypeError('defiler.depend: dependent must be a string')
}
if (typeof path$$1 !== 'string') throw new TypeError('defiler.depend: path must be a string')
if (this[_dependents].has(dependent)) {
this[_dependents].get(dependent).add(path$$1);
} else {
this[_dependents].set(dependent, new Set([path$$1]));
}
}
// private methods

@@ -420,5 +418,5 @@

if (event === '+') {
this[_waiter].init();
let done = this[_waiter].init();
this[_waiter].add(this[_processPhysicalFile](path$$1, stats));
await this[_waiter].promise;
await done;
} else if (event === '-') {

@@ -439,18 +437,18 @@ let file = this.files.get(path$$1);

let { dir, read, enc } = this[_dir$2];
let file = Object.assign(new File(), { path: path$$1, stats, enc });
if (read) file.bytes = await readFile(dir + '/' + path$$1);
let data = { path: path$$1, stats, enc };
if (read) data.bytes = await readFile(dir + '/' + path$$1);
this.paths.add(path$$1);
this[_origFiles].set(path$$1, file);
this.emit('read', { defiler: this, file });
await this[_processFile](file);
this[_origFiles].set(path$$1, data);
this.emit('read', { defiler: this, file: Object.assign(new File(), data) });
await this[_processFile](data);
}
// transform a file, store it, and process dependents
async [_processFile](origFile) {
let file = Object.assign(new File(), origFile, { paths: [origFile.path] });
async [_processFile](data) {
let file = Object.assign(new File(), data);
await this[_transformFile](file);
this.files.set(origFile.path, file);
this.files.set(data.path, file);
this.emit('file', { defiler: this, file });
this[_found](origFile.path);
this[_processDependents](origFile.path);
this[_found](data.path);
this[_processDependents](data.path);
}

@@ -463,7 +461,3 @@

try {
await this[_transform]({
defiler: this,
file,
get: dependency => this[_get](path$$1, dependency),
});
await this[_transform]({ defiler: this[_sub](path$$1), file });
} catch (error) {

@@ -485,3 +479,3 @@ this.emit('error', { defiler: this, file, error });

try {
await generator({ defiler: this, get: dependency => this[_get](symbol, dependency) });
await generator({ defiler: this[_sub](symbol) });
} catch (error) {

@@ -493,19 +487,7 @@ this.emit('error', { defiler: this, generator, error });

// wait for a file to be available and mark another file as depending on it
async [_get](dependent, path$$1) {
if (Array.isArray(path$$1)) return Promise.all(path$$1.map(path$$1 => this[_get](dependent, path$$1)))
this.depend(dependent, path$$1);
if (!this[_status] && !this.files.has(path$$1)) {
this[_waiting].set(dependent, (this[_waiting].get(dependent) || 0) + 1);
if (this[_available].has(path$$1)) {
await this[_available].get(path$$1).promise;
} else {
let resolve;
let promise = new Promise(res => (resolve = res));
this[_available].set(path$$1, { promise, resolve });
await promise;
}
this[_waiting].set(dependent, this[_waiting].get(dependent) - 1);
}
return this.files.get(path$$1)
// create a sub-defiler proxy for the given path, always overriding _dependent and only overriding _root if it is not yet set
[_sub](path$$1) {
return new Proxy(this, {
get: (_, key) => (key === _dependent || (key === _root && !this[_root]) ? path$$1 : this[key]),
})
}

@@ -512,0 +494,0 @@

@@ -11,18 +11,14 @@ import { readdir, readFile, stat, watch } from 'fs';

class File {
constructor(path = '') {
if (typeof path !== 'string') throw new TypeError('file.path must be a string')
// path of file
this[_path] = path;
// cached dir/filename/ext values
this[_dir] = this[_filename] = this[_ext] = null;
// all historical paths of file
this.paths = path ? [path] : [];
// stats of file
this.stats = null;
// encoding
this[_enc] = 'utf8';
// Buffer of file contents
this[_bytes] = null;
// string of file contents
this[_text] = null;
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
});
}

@@ -126,9 +122,9 @@

class Waiter {
// initialize/reset, and set a promise property that can be awaited
// initialize/reset, and return a promise that can be awaited
init() {
this[_count] = 0;
this.promise = new Promise((res, rej) => {
return new Promise((res, rej) => {
this[_resolve] = res;
this[_reject] = rej;
});
})
}

@@ -161,22 +157,16 @@

super();
// directory to recursively watch the contents of
this[_dir$1] = dir;
// whether to actually watch for changes (or just walk and retrieve contents and file stats)
this[_watch] = watch$$1;
// fs.watch event debounce, in milliseconds
this[_debounce] = debounce;
// paths of all (recursive) directories -> FSWatcher instances
this[_dirs] = new Map();
// paths of all (recursive) files -> file stats
this[_files] = new Map();
// paths of (recursive) 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[_processing] = false;
Object.assign(this, {
[_dir$1]: dir, // directory to recursively watch the contents of
[_watch]: watch$$1, // whether to actually watch for changes (or just walk and retrieve contents and file stats)
[_debounce]: debounce, // fs.watch event debounce, in milliseconds
[_dirs]: new Map(), // paths of all (recursive) directories -> FSWatcher instances
[_files]: 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
[_processing]: false, // whether some FSWatcher event is currently already in the process of being handled
});
}
// recurse directroy, get stats, set up FSWatcher instances
// returns array of { file, stats }
// returns array of { path, stats }
async init() {

@@ -280,3 +270,5 @@ await this[_recurse](this[_dir$1]);

_processGenerator,
_get,
_root,
_dependent,
_sub,
_processDependents,

@@ -305,42 +297,30 @@ _found,

if (
!generators[Symbol.iterator] ||
[...generators].some(generator => typeof generator !== 'function')
!Array.isArray(generators) ||
generators.some(generator => typeof generator !== 'function')
) {
throw new TypeError('defiler: generators must be a collection of functions')
throw new TypeError('defiler: generators must be an array of functions')
}
super();
// set of original paths for all physical files
this.paths = new Set();
// original paths -> original files for all physical files
this[_origFiles] = new Map();
// original paths -> transformed files for all physical and virtual files
this.files = new Map();
// null = exec not called; false = exec pending; true = exec finished
this[_status] = null;
// information about the directory to watch
dir = resolve(dir);
this[_dir$2] = { watcher: new Watcher(dir, watch$$1, debounce), dir, read, enc, watch: watch$$1 };
// the transform to run on all files
this[_transform] = transform;
// unique symbols -> registered generators
this[_generators] = new Map();
for (let generator of generators) this[_generators].set(Symbol(), generator);
// Waiter instance, to help wait for all promises in the current wave to resolve
this[_waiter] = new Waiter();
// original paths of all files currently undergoing transformation and symbols of all generators running
this[_pending] = new Set();
// original paths -> number of other files they're currently waiting on to exist
this[_waiting] = new Map();
// original paths -> { promise, resolve } objects for when awaited files become available
this[_available] = new Map();
// original paths of dependents -> set of original paths of dependencies, specifying changes to which files should trigger re-processing which other files
this[_dependents] = new Map();
// queue of pending Watcher events to handle
this[_queue$1] = [];
// whether some Watcher event is currently already in the process of being handled
this[_processing$1] = false;
Object.assign(this, {
paths: new Set(), // set of original paths for all physical files
[_origFiles]: new Map(), // original paths -> original file data for all physical files
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
[_dir$2]: { watcher: new Watcher(dir, watch$$1, debounce), dir, read, enc, watch: watch$$1 }, // information about the directory to watch
[_transform]: transform, // the transform to run on all files
[_generators]: new Map(generators.map(generator => [Symbol(), generator])), // unique symbols -> registered generators
[_waiter]: new Waiter(), // Waiter instance, to help wait for all promises in the current wave to resolve
[_pending]: new Set(), // original paths of all files currently undergoing transformation and symbols of all generators running
[_waiting]: new Map(), // original paths -> number of other files they're currently waiting on to exist
[_available]: new Map(), // original paths -> { promise, resolve } objects for when awaited files become available
[_root]: null, // (via proxy) the root dependent, for use in _dependents
[_dependent]: null, // (via proxy) the immediate dependent, for use in _waiting
[_dependents]: 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
[_processing$1]: false, // whether some Watcher event is currently already in the process of being handled
});
}
// exec
// execute everything, and return a promise that resolves when the first wave of processing is complete
async exec() {

@@ -350,3 +330,3 @@ if (this[_status] !== null) throw new Error('defiler.exec: cannot call more than once')

this[_processing$1] = true;
this[_waiter].init();
let done = this[_waiter].init();
// init the Watcher instance

@@ -367,3 +347,3 @@ let { watcher, watch: watch$$1 } = this[_dir$2];

// wait and finish up
await this[_waiter].promise;
await done;
this[_status] = true;

@@ -373,3 +353,35 @@ this[_processing$1] = false;

// post-exec methods
// wait for a file to be available and retrieve it, marking dependencies as appropriate
async get(path) {
if (
typeof path !== 'string' &&
(!Array.isArray(path) || path.some(path => typeof path !== 'string'))
) {
}
if (Array.isArray(path)) return Promise.all(path.map(path => this.get(path)))
if (this[_root]) {
if (this[_dependents].has(this[_root])) {
this[_dependents].get(this[_root]).add(path);
} else {
this[_dependents].set(this[_root], new Set([path]));
}
}
if (!this[_status] && !this.files.has(path)) {
if (this[_dependent]) {
this[_waiting].set(this[_dependent], (this[_waiting].get(this[_dependent]) || 0) + 1);
}
if (this[_available].has(path)) {
await this[_available].get(path).promise;
} else {
let resolve$$1;
let promise = new Promise(res => (resolve$$1 = res));
this[_available].set(path, { promise, resolve: resolve$$1 });
await promise;
}
if (this[_dependent]) {
this[_waiting].set(this[_dependent], this[_waiting].get(this[_dependent]) - 1);
}
}
return this.files.get(path)
}

@@ -389,16 +401,2 @@ // add a new non-physical file

// mark dependence of one file on another
depend(dependent, path) {
if (this[_status] === null) throw new Error('defiler.depend: cannot call before calling exec')
if (typeof dependent !== 'string' && !this[_generators].has(dependent)) {
throw new TypeError('defiler.depend: dependent must be a string')
}
if (typeof path !== 'string') throw new TypeError('defiler.depend: path must be a string')
if (this[_dependents].has(dependent)) {
this[_dependents].get(dependent).add(path);
} else {
this[_dependents].set(dependent, new Set([path]));
}
}
// private methods

@@ -414,5 +412,5 @@

if (event === '+') {
this[_waiter].init();
let done = this[_waiter].init();
this[_waiter].add(this[_processPhysicalFile](path, stats));
await this[_waiter].promise;
await done;
} else if (event === '-') {

@@ -433,18 +431,18 @@ let file = this.files.get(path);

let { dir, read, enc } = this[_dir$2];
let file = Object.assign(new File(), { path, stats, enc });
if (read) file.bytes = await readFile$1(dir + '/' + path);
let data = { path, stats, enc };
if (read) data.bytes = await readFile$1(dir + '/' + path);
this.paths.add(path);
this[_origFiles].set(path, file);
this.emit('read', { defiler: this, file });
await this[_processFile](file);
this[_origFiles].set(path, data);
this.emit('read', { defiler: this, file: Object.assign(new File(), data) });
await this[_processFile](data);
}
// transform a file, store it, and process dependents
async [_processFile](origFile) {
let file = Object.assign(new File(), origFile, { paths: [origFile.path] });
async [_processFile](data) {
let file = Object.assign(new File(), data);
await this[_transformFile](file);
this.files.set(origFile.path, file);
this.files.set(data.path, file);
this.emit('file', { defiler: this, file });
this[_found](origFile.path);
this[_processDependents](origFile.path);
this[_found](data.path);
this[_processDependents](data.path);
}

@@ -457,7 +455,3 @@

try {
await this[_transform]({
defiler: this,
file,
get: dependency => this[_get](path, dependency),
});
await this[_transform]({ defiler: this[_sub](path), file });
} catch (error) {

@@ -479,3 +473,3 @@ this.emit('error', { defiler: this, file, error });

try {
await generator({ defiler: this, get: dependency => this[_get](symbol, dependency) });
await generator({ defiler: this[_sub](symbol) });
} catch (error) {

@@ -487,19 +481,7 @@ this.emit('error', { defiler: this, generator, error });

// wait for a file to be available and mark another file as depending on it
async [_get](dependent, path) {
if (Array.isArray(path)) return Promise.all(path.map(path => this[_get](dependent, path)))
this.depend(dependent, path);
if (!this[_status] && !this.files.has(path)) {
this[_waiting].set(dependent, (this[_waiting].get(dependent) || 0) + 1);
if (this[_available].has(path)) {
await this[_available].get(path).promise;
} else {
let resolve$$1;
let promise = new Promise(res => (resolve$$1 = res));
this[_available].set(path, { promise, resolve: resolve$$1 });
await promise;
}
this[_waiting].set(dependent, this[_waiting].get(dependent) - 1);
}
return this.files.get(path)
// create a sub-defiler proxy for the given path, always overriding _dependent and only overriding _root if it is not yet set
[_sub](path) {
return new Proxy(this, {
get: (_, key) => (key === _dependent || (key === _root && !this[_root]) ? path : this[key]),
})
}

@@ -506,0 +488,0 @@

{
"name": "defiler",
"version": "0.12.1",
"version": "0.13.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

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