Socket
Socket
Sign inDemoInstall

broccoli-funnel

Package Overview
Dependencies
Maintainers
3
Versions
49
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

broccoli-funnel - npm Package Compare versions

Comparing version 2.0.2 to 3.0.0

7

CHANGELOG.md
# master
# 3.0.0
- [Breaking] Upgrading to latest broccoli-plugin (Breaking only because of node version drops)
- [Breaking] Modernize code: Class syntax, Async await etc.
- [Breaking] Drop Node 8, as that is EOL end of the month
- [Breaking] Drop Unsupported Node's (4, 6, 7) and add newly supported nodes (10, 12)
# 2.0.2

@@ -4,0 +11,0 @@

697

index.js
'use strict';
const fs = require('fs');
const fs = require('fs-extra');
const path = require('path-posix');
const mkdirp = require('mkdirp');
const walkSync = require('walk-sync');

@@ -13,3 +12,2 @@ const Minimatch = require('minimatch').Minimatch;

const FSTree = require('fs-tree-diff');
const rimraf = require('rimraf');
const BlankObject = require('blank-object');

@@ -52,455 +50,456 @@ const heimdall = require('heimdalljs');

Funnel.prototype = Object.create(Plugin.prototype);
Funnel.prototype.constructor = Funnel;
function Funnel(inputNode, _options) {
if (!(this instanceof Funnel)) { return new Funnel(inputNode, _options); }
class Funnel extends Plugin {
constructor(inputNode, options = {}) {
super([inputNode], {
annotation: options.annotation,
persistentOutput: true,
needsCache: false,
});
let options = _options || {};
Plugin.call(this, [inputNode], {
annotation: options.annotation,
persistentOutput: true,
needsCache: false,
});
this._includeFileCache = makeDictionary();
this._destinationPathCache = makeDictionary();
this._currentTree = new FSTree();
this._isRebuild = false;
this._includeFileCache = makeDictionary();
this._destinationPathCache = makeDictionary();
this._currentTree = new FSTree();
this._isRebuild = false;
let keys = Object.keys(options || {});
for (let i = 0, l = keys.length; i < l; i++) {
let key = keys[i];
this[key] = options[key];
}
let keys = Object.keys(options || {});
for (let i = 0, l = keys.length; i < l; i++) {
let key = keys[i];
this[key] = options[key];
}
this.destDir = this.destDir || '/';
this.count = 0;
this.destDir = this.destDir || '/';
this.count = 0;
if (this.files && typeof this.files === 'function') {
// Save dynamic files func as a different variable and let the rest of the code
// still assume that this.files is always an array.
this._dynamicFilesFunc = this.files;
delete this.files;
} else if (this.files && !Array.isArray(this.files)) {
throw new Error('Invalid files option, it must be an array or function (that returns an array).');
}
if (this.files && typeof this.files === 'function') {
// Save dynamic files func as a different variable and let the rest of the code
// still assume that this.files is always an array.
this._dynamicFilesFunc = this.files;
delete this.files;
} else if (this.files && !Array.isArray(this.files)) {
throw new Error('Invalid files option, it must be an array or function (that returns an array).');
}
if ((this.files || this._dynamicFilesFunc) && (this.include || this.exclude)) {
throw new Error('Cannot pass files option (array or function) and a include/exlude filter. You can have one or the other');
}
if ((this.files || this._dynamicFilesFunc) && (this.include || this.exclude)) {
throw new Error('Cannot pass files option (array or function) and a include/exlude filter. You can have one or the other');
}
if (this.files) {
if (this.files.filter(isNotAPattern).length !== this.files.length) {
console.warn('broccoli-funnel does not support `files:` option with globs, please use `include:` instead');
this.include = this.files;
this.files = undefined;
}
}
if (this.files) {
if (this.files.filter(isNotAPattern).length !== this.files.length) {
console.warn('broccoli-funnel does not support `files:` option with globs, please use `include:` instead');
this.include = this.files;
this.files = undefined;
}
this._setupFilter('include');
this._setupFilter('exclude');
this._matchedWalk = this.canMatchWalk();
this._instantiatedStack = (new Error()).stack;
this._buildStart = undefined;
}
this._setupFilter('include');
this._setupFilter('exclude');
canMatchWalk() {
let include = this.include;
let exclude = this.exclude;
this._matchedWalk = this.canMatchWalk();
if (!include && !exclude) { return false; }
this._instantiatedStack = (new Error()).stack;
this._buildStart = undefined;
}
let includeIsOk = true;
function isMinimatch(x) {
return x instanceof Minimatch;
}
Funnel.prototype.canMatchWalk = function() {
let include = this.include;
let exclude = this.exclude;
if (include) {
includeIsOk = include.filter(isMinimatch).length === include.length;
}
if (!include && !exclude) { return false; }
let excludeIsOk = true;
let includeIsOk = true;
if (exclude) {
excludeIsOk = exclude.filter(isMinimatch).length === exclude.length;
}
if (include) {
includeIsOk = include.filter(isMinimatch).length === include.length;
return includeIsOk && excludeIsOk;
}
let excludeIsOk = true;
_debugName() {
return this.description || this._annotation || this.name || this.constructor.name;
}
if (exclude) {
excludeIsOk = exclude.filter(isMinimatch).length === exclude.length;
_debug() {
debug(`broccoli-funnel:${this._debugName()}`).apply(null, arguments);
}
return includeIsOk && excludeIsOk;
};
_setupFilter(type) {
if (!this[type]) {
return;
}
Funnel.prototype._debugName = function() {
return this.description || this._annotation || this.name || this.constructor.name;
};
if (!Array.isArray(this[type])) {
throw new Error(`Invalid ${type} option, it must be an array. You specified \`${typeof this[type]}\`.`);
}
Funnel.prototype._debug = function() {
debug(`broccoli-funnel:${this._debugName()}`).apply(null, arguments);
};
// Clone the filter array so we are not mutating an external variable
let filters = this[type] = this[type].slice(0);
Funnel.prototype._setupFilter = function(type) {
if (!this[type]) {
return;
for (let i = 0, l = filters.length; i < l; i++) {
filters[i] = this._processPattern(filters[i]);
}
}
if (!Array.isArray(this[type])) {
throw new Error(`Invalid ${type} option, it must be an array. You specified \`${typeof this[type]}\`.`);
}
_processPattern(pattern) {
if (pattern instanceof RegExp) {
return pattern;
}
// Clone the filter array so we are not mutating an external variable
let filters = this[type] = this[type].slice(0);
let type = typeof pattern;
for (let i = 0, l = filters.length; i < l; i++) {
filters[i] = this._processPattern(filters[i]);
}
};
if (type === 'string') {
return new Minimatch(pattern);
}
Funnel.prototype._processPattern = function(pattern) {
if (pattern instanceof RegExp) {
return pattern;
}
if (type === 'function') {
return pattern;
}
let type = typeof pattern;
if (type === 'string') {
return new Minimatch(pattern);
throw new Error(`include/exclude patterns can be a RegExp, glob string, or function. You supplied \`${typeof pattern}\`.`);
}
if (type === 'function') {
return pattern;
shouldLinkRoots() {
return !this.files && !this.include && !this.exclude && !this.getDestinationPath;
}
throw new Error(`include/exclude patterns can be a RegExp, glob string, or function. You supplied \`${typeof pattern}\`.`);
};
build() {
this._buildStart = new Date();
this.destPath = path.join(this.outputPath, this.destDir);
Funnel.prototype.shouldLinkRoots = function() {
return !this.files && !this.include && !this.exclude && !this.getDestinationPath;
};
if (this.destPath[this.destPath.length - 1] === '/') {
this.destPath = this.destPath.slice(0, -1);
}
Funnel.prototype.build = function() {
this._buildStart = new Date();
this.destPath = path.join(this.outputPath, this.destDir);
let inputPath = this.inputPaths[0];
if (this.srcDir) {
inputPath = path.join(inputPath, this.srcDir);
}
if (this.destPath[this.destPath.length - 1] === '/') {
this.destPath = this.destPath.slice(0, -1);
}
if (this._dynamicFilesFunc) {
this.lastFiles = this.files;
this.files = this._dynamicFilesFunc() || [];
let inputPath = this.inputPaths[0];
if (this.srcDir) {
inputPath = path.join(inputPath, this.srcDir);
}
if (this._dynamicFilesFunc) {
this.lastFiles = this.files;
this.files = this._dynamicFilesFunc() || [];
// Blow away the include cache if the list of files is new
if (this.lastFiles !== undefined && !arrayEqual(this.lastFiles, this.files)) {
this._includeFileCache = makeDictionary();
// Blow away the include cache if the list of files is new
if (this.lastFiles !== undefined && !arrayEqual(this.lastFiles, this.files)) {
this._includeFileCache = makeDictionary();
}
}
}
let inputPathExists = fs.existsSync(inputPath);
let inputPathExists = fs.existsSync(inputPath);
let linkedRoots = false;
if (this.shouldLinkRoots()) {
linkedRoots = true;
let linkedRoots = false;
if (this.shouldLinkRoots()) {
linkedRoots = true;
/**
* We want to link the roots of these directories, but there are a few
* edge cases we must account for.
*
* 1. It's possible that the original input doesn't actually exist.
* 2. It's possible that the output symlink has been broken.
* 3. We need slightly different behavior on rebuilds.
*
* Behavior has been modified to always having an `else` clause so that
* the code is forced to account for all scenarios. Not accounting for
* all scenarios made it possible for initial builds to succeed without
* specifying `this.allowEmpty`.
*/
/**
* We want to link the roots of these directories, but there are a few
* edge cases we must account for.
*
* 1. It's possible that the original input doesn't actually exist.
* 2. It's possible that the output symlink has been broken.
* 3. We need slightly different behavior on rebuilds.
*
* Behavior has been modified to always having an `else` clause so that
* the code is forced to account for all scenarios. Not accounting for
* all scenarios made it possible for initial builds to succeed without
* specifying `this.allowEmpty`.
*/
// This is specifically looking for broken symlinks.
let outputPathExists = fs.existsSync(this.outputPath);
// This is specifically looking for broken symlinks.
let outputPathExists = fs.existsSync(this.outputPath);
// Doesn't count as a rebuild if there's not an existing outputPath.
this._isRebuild = this._isRebuild && outputPathExists;
// Doesn't count as a rebuild if there's not an existing outputPath.
this._isRebuild = this._isRebuild && outputPathExists;
/*eslint-disable no-lonely-if*/
if (this._isRebuild) {
if (inputPathExists) {
// Already works because of symlinks. Do nothing.
} else if (!inputPathExists && this.allowEmpty) {
// Make sure we're safely using a new outputPath since we were previously symlinked:
rimraf.sync(this.outputPath);
// Create a new empty folder:
mkdirp.sync(this.destPath);
} else { // this._isRebuild && !inputPathExists && !this.allowEmpty
// Need to remove it on the rebuild.
// Can blindly remove a symlink if path exists.
rimraf.sync(this.outputPath);
/*eslint-disable no-lonely-if*/
if (this._isRebuild) {
if (inputPathExists) {
// Already works because of symlinks. Do nothing.
} else if (!inputPathExists && this.allowEmpty) {
// Make sure we're safely using a new outputPath since we were previously symlinked:
fs.removeSync(this.outputPath);
// Create a new empty folder:
fs.mkdirSync(this.destPath, { recursive: true });
} else { // this._isRebuild && !inputPathExists && !this.allowEmpty
// Need to remove it on the rebuild.
// Can blindly remove a symlink if path exists.
fs.removeSync(this.outputPath);
}
} else { // Not a rebuild.
if (inputPathExists) {
// We don't want to use the generated-for-us folder.
// Instead let's remove it:
fs.removeSync(this.outputPath);
// And then symlinkOrCopy over top of it:
this._copy(inputPath, this.destPath);
} else if (!inputPathExists && this.allowEmpty) {
// Can't symlink nothing, so make an empty folder at `destPath`:
fs.mkdirSync(this.destPath, { recursive: true });
} else { // !this._isRebuild && !inputPathExists && !this.allowEmpty
throw new Error(`You specified a \`"srcDir": ${this.srcDir}\` which does not exist and did not specify \`"allowEmpty": true\`.`);
}
}
} else { // Not a rebuild.
if (inputPathExists) {
// We don't want to use the generated-for-us folder.
// Instead let's remove it:
rimraf.sync(this.outputPath);
// And then symlinkOrCopy over top of it:
this._copy(inputPath, this.destPath);
} else if (!inputPathExists && this.allowEmpty) {
// Can't symlink nothing, so make an empty folder at `destPath`:
mkdirp.sync(this.destPath);
} else { // !this._isRebuild && !inputPathExists && !this.allowEmpty
throw new Error(`You specified a \`"srcDir": ${this.srcDir}\` which does not exist and did not specify \`"allowEmpty": true\`.`);
}
/*eslint-enable no-lonely-if*/
this._isRebuild = true;
} else if (inputPathExists) {
this.processFilters(inputPath);
} else if (!this.allowEmpty) {
throw new Error(`You specified a \`"srcDir": ${this.srcDir}\` which does not exist and did not specify \`"allowEmpty": true\`.`);
} else { // !inputPathExists && this.allowEmpty
// Just make an empty folder so that any downstream consumers who don't know
// to ignore this on `allowEmpty` don't get trolled.
fs.mkdirSync(this.destPath, { recursive: true });
}
/*eslint-enable no-lonely-if*/
this._isRebuild = true;
} else if (inputPathExists) {
this.processFilters(inputPath);
} else if (!this.allowEmpty) {
throw new Error(`You specified a \`"srcDir": ${this.srcDir}\` which does not exist and did not specify \`"allowEmpty": true\`.`);
} else { // !inputPathExists && this.allowEmpty
// Just make an empty folder so that any downstream consumers who don't know
// to ignore this on `allowEmpty` don't get trolled.
mkdirp(this.destPath);
this._debug('build, %o', {
in: `${new Date() - this._buildStart}ms`,
linkedRoots,
inputPath,
destPath: this.destPath,
});
}
this._debug('build, %o', {
in: `${new Date() - this._buildStart}ms`,
linkedRoots,
inputPath,
destPath: this.destPath,
});
};
_processEntries(entries) {
return entries.filter(function(entry) {
// support the second set of filters walk-sync does not support
// * regexp
// * excludes
return this.includeFile(entry.relativePath);
}, this).map(function(entry) {
function ensureRelative(string) {
if (string.charAt(0) === '/') {
return string.substring(1);
}
return string;
}
let relativePath = entry.relativePath;
Funnel.prototype._processEntries = function(entries) {
return entries.filter(function(entry) {
// support the second set of filters walk-sync does not support
// * regexp
// * excludes
return this.includeFile(entry.relativePath);
}, this).map(function(entry) {
entry.relativePath = this.lookupDestinationPath(relativePath);
let relativePath = entry.relativePath;
this.outputToInputMappings[entry.relativePath] = relativePath;
entry.relativePath = this.lookupDestinationPath(relativePath);
return entry;
}, this);
}
this.outputToInputMappings[entry.relativePath] = relativePath;
_processPaths(paths) {
return paths.
slice(0).
filter(this.includeFile, this).
map(function(relativePath) {
let output = this.lookupDestinationPath(relativePath);
this.outputToInputMappings[output] = relativePath;
return output;
}, this);
}
return entry;
}, this);
};
processFilters(inputPath) {
let nextTree;
Funnel.prototype._processPaths = function(paths) {
return paths.
slice(0).
filter(this.includeFile, this).
map(function(relativePath) {
let output = this.lookupDestinationPath(relativePath);
this.outputToInputMappings[output] = relativePath;
return output;
}, this);
};
let instrumentation = heimdall.start('derivePatches');
let entries;
Funnel.prototype.processFilters = function(inputPath) {
let nextTree;
this.outputToInputMappings = {}; // we allow users to rename files
let instrumentation = heimdall.start('derivePatches');
let entries;
if (this.files && !this.exclude && !this.include) {
entries = this._processPaths(this.files);
// clone to be compatible with walkSync
nextTree = FSTree.fromPaths(entries, { sortAndExpand: true });
} else {
this.outputToInputMappings = {}; // we allow users to rename files
if (this._matchedWalk) {
entries = walkSync.entries(inputPath, { globs: this.include, ignore: this.exclude });
} else {
entries = walkSync.entries(inputPath);
}
if (this.files && !this.exclude && !this.include) {
entries = this._processPaths(this.files);
// clone to be compatible with walkSync
nextTree = FSTree.fromPaths(entries, { sortAndExpand: true });
} else {
if (this._matchedWalk) {
entries = walkSync.entries(inputPath, { globs: this.include, ignore: this.exclude });
} else {
entries = walkSync.entries(inputPath);
entries = this._processEntries(entries);
nextTree = FSTree.fromEntries(entries, { sortAndExpand: true });
}
entries = this._processEntries(entries);
nextTree = FSTree.fromEntries(entries, { sortAndExpand: true });
}
let patches = this._currentTree.calculatePatch(nextTree);
let patches = this._currentTree.calculatePatch(nextTree);
this._currentTree = nextTree;
this._currentTree = nextTree;
instrumentation.stats.patches = patches.length;
instrumentation.stats.entries = entries.length;
instrumentation.stats.patches = patches.length;
instrumentation.stats.entries = entries.length;
let outputPath = this.outputPath;
let outputPath = this.outputPath;
instrumentation.stop();
instrumentation.stop();
instrumentation = heimdall.start('applyPatch', ApplyPatchesSchema);
instrumentation = heimdall.start('applyPatch', ApplyPatchesSchema);
patches.forEach(function(entry) {
this._applyPatch(entry, inputPath, outputPath, instrumentation.stats);
}, this);
patches.forEach(function(entry) {
this._applyPatch(entry, inputPath, outputPath, instrumentation.stats);
}, this);
instrumentation.stop();
}
instrumentation.stop();
};
_applyPatch(entry, inputPath, _outputPath, stats) {
let outputToInput = this.outputToInputMappings;
let operation = entry[0];
let outputRelative = entry[1];
Funnel.prototype._applyPatch = function applyPatch(entry, inputPath, _outputPath, stats) {
let outputToInput = this.outputToInputMappings;
let operation = entry[0];
let outputRelative = entry[1];
if (!outputRelative) {
// broccoli itself maintains the roots, we can skip any operation on them
return;
}
if (!outputRelative) {
// broccoli itself maintains the roots, we can skip any operation on them
return;
}
let outputPath = `${_outputPath}/${outputRelative}`;
let outputPath = `${_outputPath}/${outputRelative}`;
this._debug('%s %s', operation, outputPath);
this._debug('%s %s', operation, outputPath);
switch (operation) {
case 'unlink' :
stats.unlink++;
switch (operation) {
case 'unlink' :
stats.unlink++;
fs.unlinkSync(outputPath);
break;
case 'rmdir' :
stats.rmdir++;
fs.rmdirSync(outputPath);
break;
case 'mkdir' :
stats.mkdir++;
fs.mkdirSync(outputPath);
break;
case 'change':
stats.change++;
/* falls through */
case 'create': {
if (operation === 'create') {
stats.create++;
}
fs.unlinkSync(outputPath);
break;
case 'rmdir' :
stats.rmdir++;
fs.rmdirSync(outputPath);
break;
case 'mkdir' :
stats.mkdir++;
fs.mkdirSync(outputPath);
break;
case 'change':
stats.change++;
/* falls through */
case 'create': {
if (operation === 'create') {
stats.create++;
let relativePath = outputToInput[outputRelative];
if (relativePath === undefined) {
relativePath = outputToInput[`/${outputRelative}`];
}
this.processFile(`${inputPath}/${relativePath}`, outputPath, relativePath);
break;
}
let relativePath = outputToInput[outputRelative];
if (relativePath === undefined) {
relativePath = outputToInput[`/${outputRelative}`];
}
this.processFile(`${inputPath}/${relativePath}`, outputPath, relativePath);
break;
default: throw new Error(`Unknown operation: ${operation}`);
}
default: throw new Error(`Unknown operation: ${operation}`);
}
};
Funnel.prototype.lookupDestinationPath = function(relativePath) {
if (this._destinationPathCache[relativePath] !== undefined) {
return this._destinationPathCache[relativePath];
}
lookupDestinationPath(relativePath) {
if (this._destinationPathCache[relativePath] !== undefined) {
return this._destinationPathCache[relativePath];
}
// the destDir is absolute to prevent '..' above the output dir
if (this.getDestinationPath) {
return this._destinationPathCache[relativePath] = ensureRelative(path.join(this.destDir, this.getDestinationPath(relativePath)));
// the destDir is absolute to prevent '..' above the output dir
if (this.getDestinationPath) {
return this._destinationPathCache[relativePath] = ensureRelative(path.join(this.destDir, this.getDestinationPath(relativePath)));
}
return this._destinationPathCache[relativePath] = ensureRelative(path.join(this.destDir, relativePath));
}
return this._destinationPathCache[relativePath] = ensureRelative(path.join(this.destDir, relativePath));
};
includeFile(relativePath) {
let includeFileCache = this._includeFileCache;
Funnel.prototype.includeFile = function(relativePath) {
let includeFileCache = this._includeFileCache;
if (includeFileCache[relativePath] !== undefined) {
return includeFileCache[relativePath];
}
if (includeFileCache[relativePath] !== undefined) {
return includeFileCache[relativePath];
}
// do not include directories, only files
if (relativePath[relativePath.length - 1] === '/') {
return includeFileCache[relativePath] = false;
}
// do not include directories, only files
if (relativePath[relativePath.length - 1] === '/') {
return includeFileCache[relativePath] = false;
}
let i, l, pattern;
let i, l, pattern;
// Check for specific files listing
if (this.files) {
return includeFileCache[relativePath] = this.files.indexOf(relativePath) > -1;
}
// Check for specific files listing
if (this.files) {
return includeFileCache[relativePath] = this.files.indexOf(relativePath) > -1;
}
if (this._matchedWalk) {
return true;
}
// Check exclude patterns
if (this.exclude) {
for (i = 0, l = this.exclude.length; i < l; i++) {
// An exclude pattern that returns true should be ignored
pattern = this.exclude[i];
if (this._matchedWalk) {
return true;
}
// Check exclude patterns
if (this.exclude) {
for (i = 0, l = this.exclude.length; i < l; i++) {
// An exclude pattern that returns true should be ignored
pattern = this.exclude[i];
if (this._matchesPattern(pattern, relativePath)) {
return includeFileCache[relativePath] = false;
if (this._matchesPattern(pattern, relativePath)) {
return includeFileCache[relativePath] = false;
}
}
}
}
// Check include patterns
if (this.include && this.include.length > 0) {
for (i = 0, l = this.include.length; i < l; i++) {
// An include pattern that returns true (and wasn't excluded at all)
// should _not_ be ignored
pattern = this.include[i];
// Check include patterns
if (this.include && this.include.length > 0) {
for (i = 0, l = this.include.length; i < l; i++) {
// An include pattern that returns true (and wasn't excluded at all)
// should _not_ be ignored
pattern = this.include[i];
if (this._matchesPattern(pattern, relativePath)) {
return includeFileCache[relativePath] = true;
if (this._matchesPattern(pattern, relativePath)) {
return includeFileCache[relativePath] = true;
}
}
// If no include patterns were matched, ignore this file.
return includeFileCache[relativePath] = false;
}
// If no include patterns were matched, ignore this file.
return includeFileCache[relativePath] = false;
// Otherwise, don't ignore this file
return includeFileCache[relativePath] = true;
}
_matchesPattern(pattern, relativePath) {
if (pattern instanceof RegExp) {
return pattern.test(relativePath);
} else if (pattern instanceof Minimatch) {
return pattern.match(relativePath);
} else if (typeof pattern === 'function') {
return pattern(relativePath);
}
// Otherwise, don't ignore this file
return includeFileCache[relativePath] = true;
};
throw new Error(`Pattern \`${pattern}\` was not a RegExp, Glob, or Function.`);
}
Funnel.prototype._matchesPattern = function(pattern, relativePath) {
if (pattern instanceof RegExp) {
return pattern.test(relativePath);
} else if (pattern instanceof Minimatch) {
return pattern.match(relativePath);
} else if (typeof pattern === 'function') {
return pattern(relativePath);
processFile(sourcePath, destPath /*, relativePath */) {
this._copy(sourcePath, destPath);
}
throw new Error(`Pattern \`${pattern}\` was not a RegExp, Glob, or Function.`);
};
_copy(sourcePath, destPath) {
let destDir = path.dirname(destPath);
Funnel.prototype.processFile = function(sourcePath, destPath /*, relativePath */) {
this._copy(sourcePath, destPath);
};
Funnel.prototype._copy = function(sourcePath, destPath) {
let destDir = path.dirname(destPath);
try {
symlinkOrCopy.sync(sourcePath, destPath);
} catch (e) {
if (!fs.existsSync(destDir)) {
mkdirp.sync(destDir);
}
try {
fs.unlinkSync(destPath);
symlinkOrCopy.sync(sourcePath, destPath);
} catch (e) {
// swallow the error
if (!fs.existsSync(destDir)) {
fs.mkdirSync(destDir, { recursive: true });
}
try {
fs.unlinkSync(destPath);
} catch (e) {
// swallow the error
}
symlinkOrCopy.sync(sourcePath, destPath);
}
symlinkOrCopy.sync(sourcePath, destPath);
}
}
function isMinimatch(x) {
return x instanceof Minimatch;
}
function ensureRelative(string) {
if (string.charAt(0) === '/') {
return string.substring(1);
}
return string;
}
module.exports = function funnel(...params) {
return new Funnel(...params);
};
module.exports = Funnel;
module.exports.Funnel = Funnel;
{
"name": "broccoli-funnel",
"version": "2.0.2",
"version": "3.0.0",
"description": "Broccoli plugin that allows you to filter files selected from an input node down based on regular expressions.",

@@ -16,7 +16,8 @@ "main": "index.js",

"engines": {
"node": "^4.5 || 6.* || >= 7.*"
"node": "10.* || >= 12.*"
},
"scripts": {
"test": "mocha tests/",
"test:debug": "mocha debug tests/"
"test:debug": "mocha debug tests/",
"test:debugger": "mocha --inspect-brk tests/"
},

@@ -30,11 +31,10 @@ "keywords": [

"blank-object": "^1.0.1",
"broccoli-plugin": "^1.3.0",
"debug": "^2.2.0",
"broccoli-plugin": "^3.0.0",
"debug": "^4.1.1",
"fast-ordered-set": "^1.0.0",
"fs-tree-diff": "^0.5.3",
"fs-tree-diff": "^2.0.1",
"heimdalljs": "^0.2.0",
"minimatch": "^3.0.0",
"mkdirp": "^0.5.0",
"path-posix": "^1.0.0",
"rimraf": "^2.4.3",
"rimraf": "^3.0.0",
"symlink-or-copy": "^1.0.0",

@@ -44,12 +44,10 @@ "walk-sync": "^0.3.1"

"devDependencies": {
"broccoli-builder": "^0.18.0",
"chai": "^3.2.0",
"eslint-plugin-mocha": "^4.11.0",
"fixturify": "^0.3.0",
"fs-extra": "^0.30.0",
"mocha": "~3.0.2",
"mocha-eslint": "^4.1.0",
"rimraf": "^2.3.2",
"rsvp": "^3.3.1"
"broccoli-test-helper": "^2.0.0",
"chai": "^4.2.0",
"eslint-plugin-mocha": "^6.1.1",
"fs-extra": "^8.1.0",
"mocha": "~6.2.1",
"mocha-eslint": "^5.0.0",
"rimraf": "^3.0.0"
}
}

@@ -13,3 +13,3 @@ # Broccoli Funnel

### `new Funnel(inputNode, options)`
### `funnel(inputNode, options)`

@@ -42,4 +42,4 @@ `inputNode` *{Single node}*

```javascript
var Funnel = require('broccoli-funnel');
var cssFiles = new Funnel('src/css');
const funnel = require('broccoli-funnel');
const cssFiles = funnel('src/css');

@@ -86,7 +86,7 @@ /*

```javascript
var Funnel = require('broccoli-funnel');
var MergeTrees = require('broccoli-merge-trees');
const funnel = require('broccoli-funnel');
const merge = require('broccoli-merge-trees');
// root of our source files
var projectFiles = 'src';
const projectFiles = 'src';

@@ -99,3 +99,3 @@ /* get a new node of only files in the 'src/css' directory

*/
var cssFiles = new Funnel(projectFiles, {
const cssFiles = funnel(projectFiles, {
srcDir: 'css'

@@ -110,3 +110,3 @@ });

*/
var imageFiles = new Funnel(projectFiles, {
const imageFiles = funnel(projectFiles, {
srcDir: 'icons'

@@ -116,3 +116,3 @@ });

module.exports = new MergeTrees([cssFiles, imageFiles]);
module.exports = merge([cssFiles, imageFiles]);
```

@@ -148,5 +148,5 @@

```javascript
var Funnel = require('broccoli-funnel');
const funnel = require('broccoli-funnel');
var cssFiles = new Funnel('src/css', {
const cssFiles = funnel('src/css', {
destDir: 'build'

@@ -204,8 +204,8 @@ });

```javascript
var Funnel = require('broccoli-funnel');
const funnel = require('broccoli-funnel');
// finds all files that match /todo/ and moves them
// the destDir
var todoRelatedFiles = new Funnel('src', {
include: ['todo/**/*']
const todoRelatedFiles = funnel('src', {
include: ['**/todo*']
});

@@ -258,7 +258,7 @@

```javascript
var Funnel = require('broccoli-funnel');
const funnel = require('broccoli-funnel');
// finds all files in 'src' EXCEPT `todo.js` in any directory
// or sub-directory and adds them to a node.
var nobodyLikesTodosAnyway = new Funnel('src', {
const nobodyLikesTodosAnyway = funnel('src', {
exclude: ['**/todo.js']

@@ -313,6 +313,6 @@ });

```javascript
var Funnel = require('broccoli-funnel');
const funnel = require('broccoli-funnel');
// finds these specific files and moves them to the destDir
var someFiles = new Funnel('src', {
const someFiles = funnel('src', {
files: ['css/reset.css', 'icons/check-mark.png']

@@ -350,3 +350,3 @@ });

```javascript
var node = new Funnel('packages/ember-metal/lib', {
const node = funnel('packages/ember-metal/lib', {
destDir: 'ember-metal',

@@ -364,2 +364,11 @@

## Extending Funnel
If you desire to extend funnel follow the below snippet
```js
const { Funnel } = require('broccoli-funnel');
class CustomFunnel extends Funnel {
// cutstom implementation
}
```
## ZOMG!!! TESTS?!?!!?

@@ -366,0 +375,0 @@

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