/*1* index.js: Top-level include for the `utile` module.2*3* (C) 2011, Nodejitsu Inc.4* MIT LICENSE5*6*/78var fs = require('fs'),9path = require('path'),10util = require('util');1112var utile = module.exports;1314//15// Extend the `utile` object with all methods from the16// core node `util` methods.17//18// Remark: Somehow copying `util.inspect` makes the `utile`19// object `2`. See: https://github.com/joyent/node/issues/222520//21Object.keys(util).forEach(function (key) {22if (key !== 'inspect') {23utile[key] = util[key];24}25});2627//28// @async {Object}29// Simple wrapper to `require('async')`.30//31utile.__defineGetter__('async', function () {32return require('async');33});3435//36// ### function mkdirp37// Simple wrapper to `require('mkdirp')`38//39utile.__defineGetter__('mkdirp', function () {40return require('mkdirp');41});4243//44// ### function rimraf45// Simple wrapper to `require('rimraf')`46//47utile.__defineGetter__('rimraf', function () {48return require('rimraf');49});5051//52// ### function cpr53// Simple wrapper to `require('ncp').ncp`54//55utile.__defineGetter__('cpr', function () {56return require('ncp').ncp;57});5859//60// ### @file {Object}61// Lazy-loaded `file` module62//63utile.__defineGetter__('file', function () {64return require('./file');65});6667//68// ### @base64 {Object}69// Lazy-loaded `base64` object70//71utile.__defineGetter__('base64', function () {72return require('./base64');73});7475//76// ### function each (obj, iterator)77// #### @obj {Object} Object to iterate over78// #### @iterator {function} Continuation to use on each key. `function (value, key, object)`79// Iterate over the keys of an object.80//81utile.each = function (obj, iterator) {82Object.keys(obj).forEach(function (key) {83iterator(obj[key], key, obj);84});85};8687//88// ### function find (o)89//90//91utile.find = function (obj, pred) {92var value, key;9394for (key in obj) {95value = obj[key];96if (pred(value, key)) {97return value;98}99}100};101102//103// ### function createPath (obj, path, value)104// ### @obj {Object} Object to insert value into105// ### @path {Array} List of nested keys to insert value at106// Retreives a value from given Object, `obj`, located at the107// nested keys, `path`.108//109utile.path = function (obj, path) {110var key, i;111112for (i in path) {113if (typeof obj === 'undefined') {114return undefined;115}116117key = path[i];118obj = obj[key];119}120121return obj;122};123124//125// ### function createPath (obj, path, value)126// ### @obj {Object} Object to insert value into127// ### @path {Array} List of nested keys to insert value at128// ### @value {*} Value to insert into the object.129// Inserts the `value` into the given Object, `obj`, creating130// any keys in `path` along the way if necessary.131//132utile.createPath = function (obj, path, value) {133var key, i;134135for (i in path) {136key = path[i];137if (!obj[key]) {138obj[key] = ((+i + 1 === path.length) ? value : {});139}140141obj = obj[key];142}143};144145//146// ### function mixin (target [source0, source1, ...])147// Copies enumerable properties from `source0 ... sourceN`148// onto `target` and returns the resulting object.149//150utile.mixin = function (target) {151var objs = Array.prototype.slice.call(arguments, 1);152objs.forEach(function (o) {153Object.keys(o).forEach(function (attr) {154var getter = o.__lookupGetter__(attr);155if (!getter) {156target[attr] = o[attr];157}158else {159target.__defineGetter__(attr, getter);160}161});162});163164return target;165};166167//168// ### function capitalize (str)169// #### @str {string} String to capitalize170// Capitalizes the specified `str`.171//172utile.capitalize = function (str) {173return str && str[0].toUpperCase() + str.slice(1);174};175176//177// ### function randomString (length)178// #### @length {integer} The number of bits for the random base64 string returned to contain179// randomString returns a pseude-random ASCII string (subset)180// the return value is a string of length ⌈bits/6⌉ of characters181// from the base64 alphabet.182//183utile.randomString = function (length) {184var chars, rand, i, ret, mod, bits;185186chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-';187ret = '';188// standard 4189mod = 4;190// default is 16191bits = length * mod || 64;192193// in v8, Math.random() yields 32 pseudo-random bits (in spidermonkey it gives 53)194while (bits > 0) {195// 32-bit integer196rand = Math.floor(Math.random() * 0x100000000);197//we use the top bits198for (i = 26; i > 0 && bits > 0; i -= mod, bits -= mod) {199ret += chars[0x3F & rand >>> i];200}201}202203return ret;204};205206//207// ### function filter (object, test)208// #### @obj {Object} Object to iterate over209// #### @pred {function} Predicate applied to each property. `function (value, key, object)`210// Returns an object with properties from `obj` which satisfy211// the predicate `pred`212//213utile.filter = function (obj, pred) {214var copy = Array.isArray(obj) ? [] : {};215utile.each(obj, function (val, key) {216if (pred(val, key, obj)) {217copy[key] = val;218}219});220221return copy;222};223224//225// ### function requireDir (directory)226// #### @directory {string} Directory to require227// Requires all files and directories from `directory`, returning an object228// with keys being filenames (without trailing `.js`) and respective values229// being return values of `require(filename)`.230//231utile.requireDir = function (directory) {232var result = {},233files = fs.readdirSync(directory);234235files.forEach(function (file) {236if (file.substr(-3) == '.js') {237file = file.substr(0, file.length - 3);238}239result[file] = require(path.resolve(directory, file));240});241return result;242};243244//245// ### function requireDirLazy (directory)246// #### @directory {string} Directory to require247// Lazily requires all files and directories from `directory`, returning an248// object with keys being filenames (without trailing `.js`) and respective249// values (getters) being return values of `require(filename)`.250//251utile.requireDirLazy = function (directory) {252var result = {},253files = fs.readdirSync(directory);254255files.forEach(function (file) {256if (file.substr(-3) == '.js') {257file = file.substr(0, file.length - 3);258}259result.__defineGetter__(file, function () {260return require(path.resolve(directory, file));261});262});263return result;264};265266//267// ### function clone (object)268// #### @object {Object} Object to clone269// Shallow clones the specified object.270//271utile.clone = function (object) {272return Object.keys(object).reduce(function (obj, k) {273obj[k] = object[k];274return obj;275}, {});276};277278279