2 * index.js: Top-level include for the `utile` module.
4 * (C) 2011, Nodejitsu Inc.
9 var fs = require('fs'),
10 path = require('path'),
11 util = require('util');
13 var utile = module.exports;
16 // Extend the `utile` object with all methods from the
17 // core node `util` methods.
19 Object.keys(util).forEach(function (key) {
20 utile[key] = util[key];
23 Object.defineProperties(utile, {
27 // Simple wrapper to `require('async')`.
31 return utile.async = require('async');
36 // ### function inflect
37 // Simple wrapper to `require('i')`.
41 return utile.inflect = require('i')();
46 // ### function mkdirp
47 // Simple wrapper to `require('mkdirp')`
51 return utile.mkdirp = require('mkdirp');
56 // ### function deepEqual
57 // Simple wrapper to `require('deep-equal')`
58 // Remark: deepEqual is 4x faster then using assert.deepEqual
59 // see: https://gist.github.com/2790507
63 return utile.deepEqual = require('deep-equal');
68 // ### function rimraf
69 // Simple wrapper to `require('rimraf')`
73 return utile.rimraf = require('rimraf');
79 // Simple wrapper to `require('ncp').ncp`
83 return utile.cpr = require('ncp').ncp;
89 // Lazy-loaded `file` module
93 return utile.file = require('./file');
99 // Lazy-loaded `args` module
103 return utile.args = require('./args');
108 // ### @base64 {Object}
109 // Lazy-loaded `base64` object
113 return utile.base64 = require('./base64');
118 // ### @format {Object}
119 // Lazy-loaded `format` object
123 return utile.format = require('./format');
131 // ### function rargs(_args)
132 // #### _args {Arguments} Original function arguments
134 // Top-level method will accept a javascript "arguments" object
135 // (the actual keyword "arguments" inside any scope) and return
138 utile.rargs = function (_args, slice) {
143 var len = (_args || []).length,
144 args = new Array(len - slice),
148 // Convert the raw `_args` to a proper Array.
150 for (i = slice; i < len; i++) {
151 args[i - slice] = _args[i];
158 // ### function each (obj, iterator)
159 // #### @obj {Object} Object to iterate over
160 // #### @iterator {function} Continuation to use on each key. `function (value, key, object)`
161 // Iterate over the keys of an object.
163 utile.each = function (obj, iterator) {
164 Object.keys(obj).forEach(function (key) {
165 iterator(obj[key], key, obj);
170 // ### function find (o)
173 utile.find = function (obj, pred) {
178 if (pred(value, key)) {
185 // ### function pad (str, len, chr)
186 // ### @str {String} String to pad
187 // ### @len {Number} Number of chars to pad str with
188 // ### @chr {String} Optional replacement character, defaults to empty space
189 // Appends chr to str until it reaches a length of len
191 utile.pad = function pad(str, len, chr) {
198 if (str.length < len) {
199 for (var i = 0; i < (len - str.length); i++) {
207 // ### function path (obj, path, value)
208 // ### @obj {Object} Object to insert value into
209 // ### @path {Array} List of nested keys to insert value at
210 // Retreives a value from given Object, `obj`, located at the
211 // nested keys, `path`.
213 utile.path = function (obj, path) {
217 if (typeof obj === 'undefined') {
229 // ### function createPath (obj, path, value)
230 // ### @obj {Object} Object to insert value into
231 // ### @path {Array} List of nested keys to insert value at
232 // ### @value {*} Value to insert into the object.
233 // Inserts the `value` into the given Object, `obj`, creating
234 // any keys in `path` along the way if necessary.
236 utile.createPath = function (obj, path, value) {
242 obj[key] = ((+i + 1 === path.length) ? value : {});
250 // ### function mixin (target [source0, source1, ...])
251 // Copies enumerable properties from `source0 ... sourceN`
252 // onto `target` and returns the resulting object.
254 utile.mixin = function (target) {
255 utile.rargs(arguments, 1).forEach(function (o) {
256 Object.getOwnPropertyNames(o).forEach(function(attr) {
257 var getter = Object.getOwnPropertyDescriptor(o, attr).get,
258 setter = Object.getOwnPropertyDescriptor(o, attr).set;
260 if (!getter && !setter) {
261 target[attr] = o[attr];
264 Object.defineProperty(target, attr, {
277 // ### function capitalize (str)
278 // #### @str {string} String to capitalize
279 // Capitalizes the specified `str`.
281 utile.capitalize = utile.inflect.camelize;
284 // ### function escapeRegExp (str)
285 // #### @str {string} String to be escaped
286 // Escape string for use in Javascript regex
288 utile.escapeRegExp = function (str) {
289 return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
293 // ### function randomString (length)
294 // #### @length {integer} The number of bits for the random base64 string returned to contain
295 // randomString returns a pseude-random ASCII string (subset)
296 // the return value is a string of length ⌈bits/6⌉ of characters
297 // from the base64 alphabet.
299 utile.randomString = function (length) {
300 var chars, rand, i, ret, mod, bits;
302 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-';
307 bits = length * mod || 64;
309 // in v8, Math.random() yields 32 pseudo-random bits (in spidermonkey it gives 53)
312 rand = Math.floor(Math.random() * 0x100000000);
313 //we use the top bits
314 for (i = 26; i > 0 && bits > 0; i -= mod, bits -= mod) {
315 ret += chars[0x3F & rand >>> i];
323 // ### function filter (object, test)
324 // #### @obj {Object} Object to iterate over
325 // #### @pred {function} Predicate applied to each property. `function (value, key, object)`
326 // Returns an object with properties from `obj` which satisfy
327 // the predicate `pred`
329 utile.filter = function (obj, pred) {
331 if (Array.isArray(obj)) {
333 utile.each(obj, function (val, key) {
334 if (pred(val, key, obj)) {
341 utile.each(obj, function (val, key) {
342 if (pred(val, key, obj)) {
351 // ### function requireDir (directory)
352 // #### @directory {string} Directory to require
353 // Requires all files and directories from `directory`, returning an object
354 // with keys being filenames (without trailing `.js`) and respective values
355 // being return values of `require(filename)`.
357 utile.requireDir = function (directory) {
359 files = fs.readdirSync(directory);
361 files.forEach(function (file) {
362 if (file.substr(-3) === '.js') {
363 file = file.substr(0, file.length - 3);
365 result[file] = require(path.resolve(directory, file));
371 // ### function requireDirLazy (directory)
372 // #### @directory {string} Directory to require
373 // Lazily requires all files and directories from `directory`, returning an
374 // object with keys being filenames (without trailing `.js`) and respective
375 // values (getters) being return values of `require(filename)`.
377 utile.requireDirLazy = function (directory) {
379 files = fs.readdirSync(directory);
381 files.forEach(function (file) {
382 if (file.substr(-3) === '.js') {
383 file = file.substr(0, file.length - 3);
385 Object.defineProperty(result, file, {
387 return result[file] = require(path.resolve(directory, file));
396 // ### function clone (object, filter)
397 // #### @object {Object} Object to clone
398 // #### @filter {Function} Filter to be used
399 // Shallow clones the specified object.
401 utile.clone = function (object, filter) {
402 return Object.keys(object).reduce(filter ? function (obj, k) {
403 if (filter(k)) obj[k] = object[k];
405 } : function (obj, k) {
412 // ### function camelToUnderscore (obj)
413 // #### @obj {Object} Object to convert keys on.
414 // Converts all keys of the type `keyName` to `key_name` on the
417 utile.camelToUnderscore = function (obj) {
418 if (typeof obj !== 'object' || obj === null) {
422 if (Array.isArray(obj)) {
423 obj.forEach(utile.camelToUnderscore);
427 Object.keys(obj).forEach(function (key) {
428 var k = utile.inflect.underscore(key);
434 utile.camelToUnderscore(obj[key]);
441 // ### function underscoreToCamel (obj)
442 // #### @obj {Object} Object to convert keys on.
443 // Converts all keys of the type `key_name` to `keyName` on the
446 utile.underscoreToCamel = function (obj) {
447 if (typeof obj !== 'object' || obj === null) {
451 if (Array.isArray(obj)) {
452 obj.forEach(utile.underscoreToCamel);
456 Object.keys(obj).forEach(function (key) {
457 var k = utile.inflect.camelize(key, false);
463 utile.underscoreToCamel(obj[key]);