diff --git a/lib/dest/index.js b/lib/dest/index.js index f9218e29..75fb8d10 100644 --- a/lib/dest/index.js +++ b/lib/dest/index.js @@ -3,28 +3,34 @@ var lead = require('lead'); var pumpify = require('pumpify'); var mkdirpStream = require('fs-mkdirp-stream'); -var number = require('value-or-function').number; +var createResolver = require('resolve-options'); +var config = require('./options'); var prepare = require('./prepare'); var sourcemap = require('./sourcemap'); var writeContents = require('./write-contents'); +var folderConfig = { + outFolder: { + type: 'string', + }, +}; + function dest(outFolder, opt) { - if (!opt) { - opt = {}; - } + var optResolver = createResolver(config, opt); + var folderResolver = createResolver(folderConfig, { outFolder: outFolder }); function dirpath(file, callback) { - var dirMode = number(opt.dirMode, file); + var dirMode = optResolver.resolve('dirMode', file); callback(null, file.dirname, dirMode); } var saveStream = pumpify.obj( - prepare(outFolder, opt), - sourcemap(opt), + prepare(folderResolver, optResolver), + sourcemap(optResolver), mkdirpStream.obj(dirpath), - writeContents(opt) + writeContents(optResolver) ); // Sink the output stream to start flowing diff --git a/lib/dest/options.js b/lib/dest/options.js new file mode 100644 index 00000000..14962d23 --- /dev/null +++ b/lib/dest/options.js @@ -0,0 +1,34 @@ +'use strict'; + +var config = { + cwd: { + type: 'string', + default: process.cwd, + }, + mode: { + type: 'number', + default: function(file) { + return file.stat ? file.stat.mode : null; + }, + }, + dirMode: { + type: 'number', + }, + overwrite: { + type: 'boolean', + default: true, + }, + flag: { + type: 'string', + default: function(file) { + var overwrite = this.resolve('overwrite', file); + return (overwrite ? 'w': 'wx'); + }, + }, + sourcemaps: { + type: ['string', 'boolean'], + default: false, + }, +}; + +module.exports = config; diff --git a/lib/dest/prepare.js b/lib/dest/prepare.js index 79767eda..d9f8fc62 100644 --- a/lib/dest/prepare.js +++ b/lib/dest/prepare.js @@ -3,30 +3,19 @@ var path = require('path'); var fs = require('graceful-fs'); -var koalas = require('koalas'); var through = require('through2'); -var valueOrFunction = require('value-or-function'); -var string = valueOrFunction.string; -var number = valueOrFunction.number; -var boolean = valueOrFunction.boolean; - -function prepareWrite(outFolder, opt) { - if (!opt) { - opt = {}; - } - - if (!outFolder) { +function prepareWrite(folderResolver, optResolver) { + if (!folderResolver) { throw new Error('Invalid output folder'); } function normalize(file, enc, cb) { - var defaultMode = file.stat ? file.stat.mode : null; - var mode = koalas(number(opt.mode, file), defaultMode); - var flag = koalas(boolean(opt.overwrite, file), true) ? 'w' : 'wx'; - var cwd = path.resolve(koalas(string(opt.cwd, file), process.cwd())); + var mode = optResolver.resolve('mode', file); + var flag = optResolver.resolve('flag', file); + var cwd = path.resolve(optResolver.resolve('cwd', file)); - var outFolderPath = string(outFolder, file); + var outFolderPath = folderResolver.resolve('outFolder', file); if (!outFolderPath) { return cb(new Error('Invalid output folder')); } diff --git a/lib/dest/sourcemap.js b/lib/dest/sourcemap.js index a1c376b9..c6a89613 100644 --- a/lib/dest/sourcemap.js +++ b/lib/dest/sourcemap.js @@ -2,16 +2,13 @@ var through = require('through2'); var sourcemap = require('vinyl-sourcemap'); -var valueOrFunction = require('value-or-function'); -var stringOrBool = valueOrFunction.bind(null, ['string', 'boolean']); - -function sourcemapStream(opt) { +function sourcemapStream(optResolver) { function saveSourcemap(file, enc, callback) { var self = this; - var srcMap = stringOrBool(opt.sourcemaps, file); + var srcMap = optResolver.resolve('sourcemaps', file); if (!srcMap) { return callback(null, file); diff --git a/lib/dest/write-contents/index.js b/lib/dest/write-contents/index.js index d3abd899..a4adeefa 100644 --- a/lib/dest/write-contents/index.js +++ b/lib/dest/write-contents/index.js @@ -9,27 +9,27 @@ var writeSymbolicLink = require('./write-symbolic-link'); var fo = require('../../file-operations'); -function writeContents(opt) { +function writeContents(optResolver) { function writeFile(file, enc, callback) { // If directory then mkdirp it if (file.isDirectory()) { - return writeDir(file, onWritten); + return writeDir(file, optResolver, onWritten); } // Stream it to disk yo if (file.isStream()) { - return writeStream(file, onWritten); + return writeStream(file, optResolver, onWritten); } // Write it as a symlink if (file.symlink) { - return writeSymbolicLink(file, onWritten); + return writeSymbolicLink(file, optResolver, onWritten); } // Write it like normal if (file.isBuffer()) { - return writeBuffer(file, onWritten); + return writeBuffer(file, optResolver, onWritten); } // If no contents then do nothing @@ -40,7 +40,8 @@ function writeContents(opt) { // This is invoked by the various writeXxx modules when they've finished // writing the contents. function onWritten(writeErr) { - if (fo.isFatalOverwriteError(writeErr, file.flag)) { + var flag = optResolver.resolve('flag', file); + if (fo.isFatalOverwriteError(writeErr, flag)) { return callback(writeErr); } diff --git a/lib/dest/write-contents/write-buffer.js b/lib/dest/write-contents/write-buffer.js index 502604e1..aea2afd9 100644 --- a/lib/dest/write-contents/write-buffer.js +++ b/lib/dest/write-contents/write-buffer.js @@ -2,10 +2,10 @@ var fo = require('../../file-operations'); -function writeBuffer(file, onWritten) { +function writeBuffer(file, optResolver, onWritten) { var opt = { mode: file.stat.mode, - flag: file.flag, + flag: optResolver.resolve('flag', file), }; fo.writeFile(file.path, file.contents, opt, onWriteFile); diff --git a/lib/dest/write-contents/write-dir.js b/lib/dest/write-contents/write-dir.js index 8055f3d9..d182728b 100644 --- a/lib/dest/write-contents/write-dir.js +++ b/lib/dest/write-contents/write-dir.js @@ -6,7 +6,7 @@ var mkdirp = require('fs-mkdirp-stream/mkdirp'); var fo = require('../../file-operations'); -function writeDir(file, onWritten) { +function writeDir(file, optResolver, onWritten) { mkdirp(file.path, file.stat.mode, onMkdirp); function onMkdirp(mkdirpErr) { diff --git a/lib/dest/write-contents/write-stream.js b/lib/dest/write-contents/write-stream.js index 8fff529c..b722d63f 100644 --- a/lib/dest/write-contents/write-stream.js +++ b/lib/dest/write-contents/write-stream.js @@ -3,11 +3,11 @@ var fo = require('../../file-operations'); var readStream = require('../../src/read-contents/read-stream'); -function writeStream(file, onWritten) { +function writeStream(file, optResolver, onWritten) { var opt = { mode: file.stat.mode, // TODO: need to test this (node calls this `flags` property) - flag: file.flag, + flag: optResolver.resolve('flag', file), }; // TODO: is this the best API? diff --git a/lib/dest/write-contents/write-symbolic-link.js b/lib/dest/write-contents/write-symbolic-link.js index 82c09fda..c33b15bb 100644 --- a/lib/dest/write-contents/write-symbolic-link.js +++ b/lib/dest/write-contents/write-symbolic-link.js @@ -4,7 +4,7 @@ var fs = require('graceful-fs'); var fo = require('../../file-operations'); -function writeSymbolicLink(file, onWritten) { +function writeSymbolicLink(file, optResolver, onWritten) { // TODO handle symlinks properly fs.symlink(file.symlink, file.path, function(symlinkErr) { if (fo.isFatalOverwriteError(symlinkErr)) { diff --git a/lib/src/index.js b/lib/src/index.js index 379716e7..6f531cea 100644 --- a/lib/src/index.js +++ b/lib/src/index.js @@ -4,7 +4,9 @@ var gs = require('glob-stream'); var pumpify = require('pumpify'); var toThrough = require('to-through'); var isValidGlob = require('is-valid-glob'); +var createResolver = require('resolve-options'); +var config = require('./options'); var prepare = require('./prepare'); var wrapVinyl = require('./wrap-vinyl'); var sourcemap = require('./sourcemap'); @@ -12,9 +14,7 @@ var readContents = require('./read-contents'); var resolveSymlinks = require('./resolve-symlinks'); function src(glob, opt) { - if (!opt) { - opt = {}; - } + var optResolver = createResolver(config, opt); if (!isValidGlob(glob)) { throw new Error('Invalid glob argument: ' + glob); @@ -22,11 +22,11 @@ function src(glob, opt) { var streams = [ gs(glob, opt), - wrapVinyl(opt), - resolveSymlinks(opt), - prepare(opt), - readContents(opt), - sourcemap(opt), + wrapVinyl(optResolver), + resolveSymlinks(optResolver), + prepare(optResolver), + readContents(optResolver), + sourcemap(optResolver), ]; var outputStream = pumpify.obj(streams); diff --git a/lib/src/options.js b/lib/src/options.js new file mode 100644 index 00000000..bd77312c --- /dev/null +++ b/lib/src/options.js @@ -0,0 +1,29 @@ +'use strict'; + +var config = { + buffer: { + type: 'boolean', + default: true, + }, + read: { + type: 'boolean', + default: true, + }, + since: { + type: 'date', + }, + stripBOM: { + type: 'boolean', + default: true, + }, + sourcemaps: { + type: 'boolean', + default: false, + }, + resolveSymlinks: { + type: 'boolean', + default: true, + }, +}; + +module.exports = config; diff --git a/lib/src/prepare.js b/lib/src/prepare.js index ce10df9e..5fa18dff 100644 --- a/lib/src/prepare.js +++ b/lib/src/prepare.js @@ -1,26 +1,16 @@ 'use strict'; var through = require('through2'); -var valueOrFunction = require('value-or-function'); -var date = valueOrFunction.date; - -function prepareRead(opt) { - if (!opt) { - opt = {}; - } +function prepareRead(optResolver) { function normalize(file, enc, callback) { + var since = optResolver.resolve('since', file); + // Skip this file if since option is set and current file is too old - if (opt.since != null) { - var since = date(opt.since, file); - if (since === null) { - return callback(new Error('Invalid since option')); - } - if (file.stat && file.stat.mtime <= since) { - return callback(); - } + if (file.stat && file.stat.mtime <= since) { + return callback(); } return callback(null, file); diff --git a/lib/src/read-contents/index.js b/lib/src/read-contents/index.js index 2a75b1cd..81f263cc 100644 --- a/lib/src/read-contents/index.js +++ b/lib/src/read-contents/index.js @@ -1,42 +1,40 @@ 'use strict'; var through = require('through2'); -var valueOrFunction = require('value-or-function'); -var koalas = require('koalas'); var readDir = require('./read-dir'); var readStream = require('./read-stream'); var readBuffer = require('./read-buffer'); var readSymbolicLink = require('./read-symbolic-link'); -var boolean = valueOrFunction.boolean; - -function readContents(opt) { +function readContents(optResolver) { function readFile(file, enc, callback) { // Skip reading contents if read option says so - if (!koalas(boolean(opt.read, file), true)) { + var read = optResolver.resolve('read', file); + if (!read) { return callback(null, file); } // Don't fail to read a directory if (file.isDirectory()) { - return readDir(file, opt, onRead); + return readDir(file, optResolver, onRead); } // Process symbolic links included with `resolveSymlinks` option if (file.stat && file.stat.isSymbolicLink()) { - return readSymbolicLink(file, opt, onRead); + return readSymbolicLink(file, optResolver, onRead); } // Read and pass full contents - if (koalas(boolean(opt.buffer, file), true)) { - return readBuffer(file, opt, onRead); + var buffer = optResolver.resolve('buffer', file); + if (buffer) { + return readBuffer(file, optResolver, onRead); } // Don't buffer anything - just pass streams - return readStream(file, opt, onRead); + return readStream(file, optResolver, onRead); // This is invoked by the various readXxx modules when they've finished // reading the contents. diff --git a/lib/src/read-contents/read-buffer.js b/lib/src/read-contents/read-buffer.js index ab3713ad..7f467bf3 100644 --- a/lib/src/read-contents/read-buffer.js +++ b/lib/src/read-contents/read-buffer.js @@ -3,12 +3,7 @@ var fs = require('graceful-fs'); var stripBom = require('strip-bom'); -var valueOrFunction = require('value-or-function'); -var koalas = require('koalas'); - -var boolean = valueOrFunction.boolean; - -function bufferFile(file, opt, onRead) { +function bufferFile(file, optResolver, onRead) { fs.readFile(file.path, onReadFile); function onReadFile(readErr, data) { @@ -16,7 +11,8 @@ function bufferFile(file, opt, onRead) { return onRead(readErr); } - if (koalas(boolean(opt.stripBOM, file), true)) { + var stripBOM = optResolver.resolve('stripBOM', file); + if (stripBOM) { file.contents = stripBom(data); } else { file.contents = data; diff --git a/lib/src/read-contents/read-dir.js b/lib/src/read-contents/read-dir.js index 63cc706b..be7262b7 100644 --- a/lib/src/read-contents/read-dir.js +++ b/lib/src/read-contents/read-dir.js @@ -1,6 +1,6 @@ 'use strict'; -function readDir(file, opt, onRead) { +function readDir(file, optResolver, onRead) { // Do nothing for now onRead(); } diff --git a/lib/src/read-contents/read-stream.js b/lib/src/read-contents/read-stream.js index 24f4d616..95ec2250 100644 --- a/lib/src/read-contents/read-stream.js +++ b/lib/src/read-contents/read-stream.js @@ -3,16 +3,12 @@ var fs = require('graceful-fs'); var stripBom = require('strip-bom-stream'); var lazystream = require('lazystream'); +var createResolver = require('resolve-options'); -var valueOrFunction = require('value-or-function'); -var koalas = require('koalas'); - -var boolean = valueOrFunction.boolean; - -function streamFile(file, opt, onRead) { - if (typeof opt === 'function') { - onRead = opt; - opt = {}; +function streamFile(file, optResolver, onRead) { + if (typeof optResolver === 'function') { + onRead = optResolver; + optResolver = createResolver(); } var filePath = file.path; @@ -21,7 +17,8 @@ function streamFile(file, opt, onRead) { return fs.createReadStream(filePath); }); - if (koalas(boolean(opt.stripBOM, file), true)) { + var stripBOM = optResolver.resolve('stripBOM', file); + if (stripBOM) { file.contents = file.contents.pipe(stripBom()); } diff --git a/lib/src/read-contents/read-symbolic-link.js b/lib/src/read-contents/read-symbolic-link.js index 89dc2f01..47e24cdd 100644 --- a/lib/src/read-contents/read-symbolic-link.js +++ b/lib/src/read-contents/read-symbolic-link.js @@ -2,7 +2,7 @@ var fs = require('graceful-fs'); -function readLink(file, opt, onRead) { +function readLink(file, optResolver, onRead) { fs.readlink(file.path, onReadlink); function onReadlink(readErr, target) { diff --git a/lib/src/resolve-symlinks.js b/lib/src/resolve-symlinks.js index c769a824..5e322c2d 100644 --- a/lib/src/resolve-symlinks.js +++ b/lib/src/resolve-symlinks.js @@ -3,11 +3,7 @@ var through = require('through2'); var fs = require('graceful-fs'); -var koalas = require('koalas'); -var valueOrFunction = require('value-or-function'); -var boolean = valueOrFunction.boolean; - -function resolveSymlinks(opt) { +function resolveSymlinks(optResolver) { // A stat property is exposed on file objects as a (wanted) side effect function resolveFile(file, enc, callback) { @@ -25,7 +21,7 @@ function resolveSymlinks(opt) { return callback(null, file); } - var resolveSymlinks = koalas(boolean(opt.resolveSymlinks, file), true); + var resolveSymlinks = optResolver.resolve('resolveSymlinks', file); if (!resolveSymlinks) { return callback(null, file); diff --git a/lib/src/sourcemap.js b/lib/src/sourcemap.js index 013583ac..e03971f1 100644 --- a/lib/src/sourcemap.js +++ b/lib/src/sourcemap.js @@ -2,14 +2,11 @@ var through = require('through2'); var sourcemap = require('vinyl-sourcemap'); -var valueOrFunction = require('value-or-function'); -var boolean = valueOrFunction.boolean; - -function sourcemapStream(opt) { +function sourcemapStream(optResolver) { function addSourcemap(file, enc, callback) { - var srcMap = boolean(opt.sourcemaps, file); + var srcMap = optResolver.resolve('sourcemaps', file); if (!srcMap) { return callback(null, file); diff --git a/lib/src/wrap-vinyl.js b/lib/src/wrap-vinyl.js index eff8a01f..883c5575 100644 --- a/lib/src/wrap-vinyl.js +++ b/lib/src/wrap-vinyl.js @@ -3,7 +3,7 @@ var File = require('vinyl'); var through = require('through2'); -function wrapVinyl(opt) { +function wrapVinyl() { function wrapFile(globFile, enc, callback) { diff --git a/lib/symlink/index.js b/lib/symlink/index.js index abe029e2..e76a0a08 100644 --- a/lib/symlink/index.js +++ b/lib/symlink/index.js @@ -1,28 +1,28 @@ 'use strict'; var path = require('path'); -var os = require('os'); var fs = require('graceful-fs'); var pumpify = require('pumpify'); var through = require('through2'); -var valueOrFunction = require('value-or-function'); -var koalas = require('koalas'); var lead = require('lead'); var mkdirpStream = require('fs-mkdirp-stream'); +var createResolver = require('resolve-options'); var fo = require('../file-operations'); -var prepare = require('./prepare'); -var number = valueOrFunction.number; -var boolean = valueOrFunction.boolean; +var config = require('./options'); +var prepare = require('./prepare'); -var isWindows = (os.platform() === 'win32'); +var folderConfig = { + outFolder: { + type: 'string', + }, +}; function symlink(outFolder, opt) { - if (!opt) { - opt = {}; - } + var optResolver = createResolver(config, opt); + var folderResolver = createResolver(folderConfig, { outFolder: outFolder }); function linkFile(file, enc, callback) { // Fetch the path as it was before prepare.dest() @@ -41,11 +41,11 @@ function symlink(outFolder, opt) { // For example, JetBrains product lines will delete the entire // contents of the TARGET directory because the product does not // realize it's a symlink as the JVM and Node return false for isSymlink. - var useJunctions = koalas(boolean(opt.useJunctions, file), (isWindows && isDirectory)); + var useJunctions = optResolver.resolve('useJunctions', file); var symDirType = useJunctions ? 'junction' : 'dir'; var symType = isDirectory ? symDirType : 'file'; - var isRelative = koalas(boolean(opt.relative, file), false); + var isRelative = optResolver.resolve('relative', file); // This is done inside prepareWrite to use the adjusted file.base property if (isRelative && !useJunctions) { @@ -54,7 +54,8 @@ function symlink(outFolder, opt) { // Because fs.symlink does not allow atomic overwrite option with flags, we // delete and recreate if the link already exists and overwrite is true. - if (file.flag === 'w') { + var flag = optResolver.resolve('flag', file); + if (flag === 'w') { // TODO What happens when we call unlink with windows junctions? fs.unlink(file.path, onUnlink); } else { @@ -69,7 +70,7 @@ function symlink(outFolder, opt) { } function onSymlink(symlinkErr) { - if (fo.isFatalOverwriteError(symlinkErr, file.flag)) { + if (fo.isFatalOverwriteError(symlinkErr, flag)) { return callback(symlinkErr); } callback(null, file); @@ -77,13 +78,13 @@ function symlink(outFolder, opt) { } function dirpath(file, callback) { - var dirMode = number(opt.dirMode, file); + var dirMode = optResolver.resolve('dirMode', file); callback(null, file.dirname, dirMode); } var stream = pumpify.obj( - prepare(outFolder, opt), + prepare(folderResolver, optResolver), mkdirpStream.obj(dirpath), through.obj(linkFile) ); diff --git a/lib/symlink/options.js b/lib/symlink/options.js new file mode 100644 index 00000000..6b9b36cd --- /dev/null +++ b/lib/symlink/options.js @@ -0,0 +1,45 @@ +'use strict'; + +var os = require('os'); + +var isWindows = (os.platform() === 'win32'); + +var config = { + useJunctions: { + type: 'boolean', + default: function(file) { + var isDirectory = file.isDirectory(); + return (isWindows && isDirectory); + }, + }, + relative: { + type: 'boolean', + default: false, + }, + cwd: { + type: 'string', + default: process.cwd, + }, + mode: { + type: 'number', + default: function(file) { + return file.stat ? file.stat.mode : null; + }, + }, + dirMode: { + type: 'number', + }, + overwrite: { + type: 'boolean', + default: true, + }, + flag: { + type: 'string', + default: function(file) { + var overwrite = this.resolve('overwrite', file); + return (overwrite ? 'w': 'wx'); + }, + }, +}; + +module.exports = config; diff --git a/lib/symlink/prepare.js b/lib/symlink/prepare.js index 245911f4..e1ec5ac1 100644 --- a/lib/symlink/prepare.js +++ b/lib/symlink/prepare.js @@ -5,30 +5,19 @@ var path = require('path'); var fs = require('graceful-fs'); -var koalas = require('koalas'); var through = require('through2'); -var valueOrFunction = require('value-or-function'); -var string = valueOrFunction.string; -var number = valueOrFunction.number; -var boolean = valueOrFunction.boolean; - -function prepareSymlink(outFolder, opt) { - if (!opt) { - opt = {}; - } - - if (!outFolder) { +function prepareSymlink(folderResolver, optResolver) { + if (!folderResolver) { throw new Error('Invalid output folder'); } function normalize(file, enc, cb) { - var defaultMode = file.stat ? file.stat.mode : null; - var mode = koalas(number(opt.mode, file), defaultMode); - var flag = koalas(boolean(opt.overwrite, file), true) ? 'w' : 'wx'; - var cwd = path.resolve(koalas(string(opt.cwd, file), process.cwd())); + var mode = optResolver.resolve('mode', file); + var flag = optResolver.resolve('flag', file); + var cwd = path.resolve(optResolver.resolve('cwd', file)); - var outFolderPath = string(outFolder, file); + var outFolderPath = folderResolver.resolve('outFolder', file); if (!outFolderPath) { return cb(new Error('Invalid output folder')); } diff --git a/package.json b/package.json index 2f0a952e..4cb4f626 100644 --- a/package.json +++ b/package.json @@ -31,11 +31,11 @@ "glob-stream": "^6.1.0", "graceful-fs": "^4.0.0", "is-valid-glob": "^0.3.0", - "koalas": "^1.0.1", "lazystream": "^1.0.0", "lead": "^1.0.0", "object-assign": "^4.0.0", "pumpify": "^1.3.5", + "resolve-options": "^1.0.0", "strip-bom": "^2.0.0", "strip-bom-stream": "^1.0.0", "through2": "^2.0.0",