inote-util v1.17.2
inote-util

A collection of utility functions and classes for Node.js.
Contents
- Features - method-by-method description of the utilities.
- Installing - how to install from npm or source.
- Licensing -
inote-utilis made available under an MIT License. - How to Contribute - tips on reporting issues, creating pull-requests for or just generally hacking
inote-util.
Using
note-util exports a number of objects, each containing several utility functions.
Hence, require(‘note-util’) will return a map with several sub-objects (ArrayUtil, AsyncUtil, etc.)
There are two common idioms for handling this.
Idiom 1: Keep a handle to this “parent” object:
var IU = require(“note-util”);
IU.LogUtil.tlog(“Here is a random string:”, IU.RandomUtil.random_alphanumeric());Idiom 2: Keep a handle to the individual utilities:
var LogUtil = require(“note-util”).LogUtil;
var RandomUtil = require(“note-util”).RandomUtil;
LogUtil.tlog(“Here is a random string:”, RandomUtil.random_alphanumeric());Personally, the author prefers the second approach, but the difference is almost entirely cosmetic. In particular, note that in Node.js require-ing the same module multiple times DOES NOT reload or reparse the files in the module. The file is only load once.
The following section lists methods under the associated object. E.g., under NetUtil you’ll find get_unused_port(). This means that the get_unused_port method is exported within the top-level object named “NetUtil” and could be accessed via:
var gup = require(“note-util”).NetUtil.get_unused_port;Features
Feature Index
ArrayUtil | AsyncUtil | ColorUtil | Config | DateUtil | FileUtil | FileUtil MIME | IOUtil | L10nUtil | LogUtil | NetUtil | NumberUtil | ObjectUtil | RandomUtil | SimpleCache | Stopwatch | StringUtil | Util | WebUtil | WorkQueue | ZipUtil | Errors
ArrayUtil
- lpad(value,width,pad) - adds
padelements to the beginning ofvalueuntilvalueiswidthelements long. (Also accepts strings, seeStringUtil.lpad, which is identical.) - rpad(value,width,pad) - adds
padelements to the end ofvalueuntilvalueiswidthelements long. (Also accepts strings, seeStringUtil.rpad, which is identical.) - smart_join(array,delim,last_delim) - identical to
Array.join, except the specifiedlast_delimis used between the last two elements (if any). E.g.,smart_join(["Tom","Dick","Harry"],", "," and ")yieldsTom, Dick and Harry. - trim_trailing_null(array) - returns a copy of
arraywith trailingnullelements removed - right_shift_args(...) - returns an array the same length as the given arguments, but any trailing
nullvalues are converted to leadingnullvalues. (Most useful in the CoffeeScript idiom[a,b,c,d] = right_shift_args(a,b,c,d).) - paginate_list(list[,offset=0,limit=20]) - returns the specified section of the given array.
- subset_of(a,b) / ArrayUtil.is_subset_of(a,b) - returns
trueif every element of array a is also an element of b. - strict_subset_of(a,b) / ArrayUtil.is_strict_subset_of(a,b) - returns
trueif every element of array a appears exacty the same number of times in array b as it does in array a. (E.g.,['a','a','b']is subset of but not a strict subset of['a','b','c'], according to this definition). - sets_are_equal(a,b) - compares arrays as if they were sets.
- arrays_are_equal(a,b) -
trueif and only if array a and array b contain the exact same elements in the exact same order. DEPRECATED: please useObjectUtil.deep_equal - uniquify(array,key) - returns a clone of
arraywith duplicate values removed. When the array contains objects (maps) and akeyis provided, two elements will be considered duplicates if they have the same value for the attributekey.
AsyncUtil
- wait_until(predicate,interval,callback) / wait_for(predicate,interval,callback) - polls
predicate()everyintervalmilliseconds until it returnstrue(or throws an exception). Callback signature is(err,complete)wherecompleteistrueif and only ifpredicate()returnedtrue.intervaldefaults to100. - wait(delay,callback) / set_timeout(delay,callback) / setTimeout(delay,callback) - just like
setTimeout(callback,delay)but with a more CoffeeScript-friendly parameter order. - cancel_wait(id) / clear_timeout(id) / clearTimeout(id) - alias for
window.clearTimeout(id). - interval(delay,callback) / set_interval(delay,callback) / setInterval(delay,callback) - just like
setInterval(callback,delay)but with a more CoffeeScript-friendly parameter order. - cancel_interval(id) / cancelInterval(id) / clear_interval(id) / clearlInterval(id) - alias for
window.clearInterval(id). - for_async(initialize,condition,action,increment,options,whendone) - executes an asynchronous
forloop. Accepts 5 function-valued parameters:initialize- an initialization function (no arguments passed, no return value is expected);condition- a predicate that indicates whether we should continue looping (no arguments passed, a boolean value is expected to be returned);action- the action to take (a single callback function is passed and should be invoked at the end of the action, no return value is expected);increment- called at the end of everyaction, prior tocondition(no arguments passed, no return value is expected);options- optional options mapdelay- time added before each successive invocation, in millisecondstimeout- max time to wait for an action to complete, in millisecondscatch_exceptions- boolean
whendone- called at the end of the loop (whenconditionreturnsfalse), (no arguments passed, no return value is expected).
- for_each_async(list,action,options,whendone) - executes an asynchronous
forEachloop. Accepts 3 (or 4) parameters:list- the array to iterate over;action- a function with the signature(value,index,list,next)indicating the action to take for each element (must callnextfor processing to continue);options- optional options mapdelay- time added before each successive invocation, in millisecondstimeout- max time to wait for an action to complete, in millisecondscatch_exceptions- boolean
whendone- called at the end of the loop.
- fork(methods,args_for_methods,options,callback) - runs the given array of methods "simultaneously" (asynchronously), invoking
callbackwhen they are all complete:options- optional options mapdelay- time added before each successive invocation, in millisecondstimeout- max time to wait for an action to complete, in millisecondscatch_exceptions- boolean
- throttled_fork(max_parallel,methods,args_for_methods,options,callback) - just like
fork, but never running more thanmax_parallelfunctions at the same time. - fork_for_each_async(list,action,options,whendone) - like
for_each_asyncbut runningactionin parallel for each element of thelist. Thewhendonecallback is provided with a list of "responses", in the same order as the original list. - throttled_fork_for_each_async(max_parallel,list,action,options,whendone) - like
fork_for_each_asyncbut running at mostmax_parallelmethods at any one time. - invoke_with_timeout(method,args,options,callback)
- maybe_invoke_with_timeout(method,args,options,callback)
- procedure() - generates a
Sequencerobject, as described below
The Sequencer
The methods Util.procedure(), AsyncUtil.procedure(), and new Sequencer() will create a new "sequencer" object that provides a simple way to "flatten" long chains of nested asynchronous methods.
For example, rather than writing:
method_one( function(e,a,b) {
method_two(a, b, function() {
method_three( function(e,c,d) {
and_so_on();
});
});
});We can flatten the calls out like this:
var procedure = AsyncUtil.procedure();
procedure.first( method_one );
procedure.then( method_two );
procedure.then( method_three );
procedure.then( and_so_on );
procedure.run();Each call to then appends the given callback method to the chain.
Each callback method is passed a next_step function that must be called to trigger the next step in the processing.
Note that any arguments passed to next_step() will be passed to the next method in the sequence (with the next function appended). For example, given a method in the sequence such as:
procedure.next(function(next_step) {
next_step(1,"A",[]);
});The following method in the procedure will be invoked with the following signature:
the_next_method_in_the_sequence(1,"A",[],next_step);Hence the typical use of the class looks something like this:
var s = new Sequencer()
s.first( function(done) {
// do something, then invoke the callback
done();
});
s.next( function(done) {
// do something, then invoke the callback
done();
});
s.next( function(done) {
// do something, then invoke the callback
done();
});
s.run();When run is invoked, each asynchronous method is executed in sequence.
The first method is optional (you can just use next instead), but when invoked first will remove any methods previously added to the chain.
You last methods is an optional short-hand for adding one final method to the chain and then running it. E.g., the last two lines of our example:
procedure.then( and_so_on )
procedure.run()Could be re-written:
procedure.last( and_so_on )Note that the sequence is not cleared when run is invoked, so one may invoke run more than once to execute the sequence again.
ColorUtil
- hex_to_rgb_triplet(hex) - converts a hex-based
#rrggbbstring to decimal[r,g,b]values. - hex_to_rgb_string(hex) - converts a hex-based
#rrggbbstring to a string of the formrgb(r,g,b). - rgb_string_to_triplet(rgb) - converts a string of the form
rgb(r,g,b)to decimal[r,g,b]values. - rgb_triplet_to_string(r,g,b) - convert an array or sequence of r, g, b values to a string of the form
rgb(r,g,b).
Config
A thin wrapper around nconf providing a consistent way to load configuration data from files or the environment.
Note that config now allows // and /* */ style comments in JSON files.
Example of use
var config = require('inote-util').config.init();
var prop = config.get('my:property');Config will load the configuration from several sources.
In order of precedence:
"Override" values passed to the
initfunction.Command line parameters (
--name value).Environment variables. Note that
__can be used in place of:as a delimiter.A JSON-format configuration file (from a location deterimined by
NODE_ENV,config_dirorconfig_file).A "default" JSON-format configuration file at
${config_dir}/config.json."Default" values passed to the
initfunction.
To discover a configuration file (as used in step 3 above), Config will:
Look for
NODE_ENV,config_dirorconfig_fileenvironment variables.If
config_diris set, the value will be used as the "parent" directory of the configuration files. (Ifconfig_diris not set, it defaults to the directoryconfigwithin the working directory from which the current Node.js process was launched.)If
NODE_ENVis set and a file named${NODE_ENV}.jsonexists within theconfig_dir, that file will be used.If
config_fileis set, that file will be used.
DateUtil
- start_time - timestamp at which
inote-utilwas loaded (hence approximately the time the application was started in most circumstances). - duration(end_time,begin_time) - returns an object that breaks-down the time between
begin_timeandend_timein several ways (as described below). When missing,end_timedefaults toDate.now()andbegin_timedefaults tostart_time. - iso_8601_regexp() - returns a regular expression that can be used to validate an ISO 8601 formatted date.
Here is an example of the object returned by the DateUtil.duration, with brief annotations.
{
"begin":1462806430444,
"end":1462851730757,
"delta":45300313,
"in_millis":{ // MILLISECOND VALUE OF EACH "PART" OF THE DURATION
"millis":313, // <= delta % (1000)
"seconds":313, // <= delta % (1000 * 60)
"minutes":2100313, // <= delta % (1000 * 60 * 60)
"hours":45300313, // <= delta % (1000 * 60 * 60 * 24)
"days":45300313, // <= delta % (1000 * 60 * 60 * 24 * 7
"weeks":45300313, // <= delta % (1000 * 60 * 60 * 24 * 7 * 52
"years":45300313 // <= delta
},
"raw":{ // ELEMENTS FROM `IN_MILLIS`, CONVERTED TO RELEVANT UNIT
"millis":313, // <= in_millis.millis
"seconds":0.313, // <= in_millis.seconds / (1000)
"minutes":35.00521666666667, // <= in_millis.minutes / (1000 * 60)
"hours":12.583420277777778, // <= in_millis.hours / (1000 * 60 * 60)
"days":0.5243091782407407, // <= in_millis.days / (1000 * 60 * 60 * 24)
"weeks":0.07490131117724867, // <= in_millis.weeks / (1000 * 60 * 60 * 24 * 7)
"years":0.00020520907171848953 // <= in_millis.years / (1000 * 60 * 60 * 24 * 7 * 365)
},
"whole":{ // RAW VALUES ROUNDED DOWN TO NEAREST INTEGER
"millis":313,
"seconds":0,
"minutes":35,
"hours":12,
"days":0,
"weeks":0,
"years":0
},
"array":{ // SET OF DURATION ELEMENTS IN ARRAYS
"full":{ // FULL = ALL UNITS, EVEN WHEN 0
"values":[0,0,0,12,35,0,313],
"short":["0y","0w","0d","12h","35m","0s","313m"],
"long":["0 years","0 weeks","0 days","12 hours","35 minutes","0 seconds","313 milliseconds"],
"no_millis":{ // SAME AS PARENT BUT IGNORING MILLISECONDS
"values":[0,0,0,12,35,0],
"short":["0y","0w","0d","12h","35m","0s"],
"long":["0 years","0 weeks","0 days","12 hours","35 minutes","0 seconds"]
}
},
"brief":{ // BRIEF = SKIP TO LARGEST NON-ZERO UNIT, THEN INCLUDE ALL
"values":[12,35,0,313],
"short":["12h","35m","0s","313m"],
"long":["12 hours","35 minutes","0 seconds","313 millis"],
"no_millis":{
"values":[12,35,0],
"short":["12h","35m","0s"],
"long":["12 hours","35 minutes","0 seconds"]
}
},
"min":{ // MIN = ONLY THE NON-ZERO VALUES
"units":["hour","minute","millisecond"],
"short":["12h","35m","313m"],
"long":["12 hours","35 minutes","313 milliseconds"],
"no_millis":{
"units":["hour","minute"],
"short":["12h","35m"],
"long":["12 hours","35 minutes"]
}
}
},
"string":{ // SIMILAR TO "ARRAY" BUT WITH STRINGS
"full":{
"micro":"0y0w0d12h35m0s313m",
"short":"0y 0w 0d 12h 35m 0s 313m",
"long":"0 years 0 weeks 0 days 12 hours 35 minutes 0 seconds 313 milliseconds",
"verbose":"0 years, 0 weeks, 0 days, 12 hours, 35 minutes, 0 seconds and 313 milliseconds",
"no_millis":{
"micro":"0y0w0d12h35m0s",
"short":"0y 0w 0d 12h 35m 0s",
"long":"0 years 0 weeks 0 days 12 hours 35 minutes 0 seconds",
"verbose":"0 years, 0 weeks, 0 days, 12 hours, 35 minutes and 0 seconds"
}
},
"brief":{
"micro":"12h35m0s313m",
"short":"12h 35m 0s 313m",
"long":"12 hours 35 minutes 0 seconds 313 millis",
"verbose":"12 hours, 35 minutes, 0 seconds and 313 millis",
"no_millis":{
"micro":"12h35m0s",
"short":"12h 35m 0s",
"long":"12 hours 35 minutes 0 seconds",
"verbose":"12 hours, 35 minutes and 0 seconds"
}
},
"min":{
"micro":"12h35m313m",
"short":"12h 35m 313m",
"long":"12 hours 35 minutes 313 milliseconds",
"verbose":"12 hours, 35 minutes and 313 milliseconds",
"no_millis":{
"micro":"12h35m",
"short":"12h 35m",
"long":"12 hours 35 minutes",
"verbose":"12 hours, 35 minutes and 48 seconds"
}
}
}
}FileUtil
- file_age(file,callback) / file_age_sync(file) - obtain the age of a file (time since last modfied) in milliseconds
- file_mtime(file,callback) / file_mtime_sync(file)- obtain the Unix epoch timestamp at which a file was last modified
- ls(dir[,options],callback) - list the files in a directory; options:
recurse- whentrue, perform the operation recursivelypattern- when a non-nullRegExp, only list files matching the specified patterntypes- an array or string containingfileordirectory
- is_dir(filename,callback) - test if the specified filename is a directory
- is_file(filename,callback) - test if the specified filename is a plain file (not a directory).
- sanitize_filename(filename) - removes invalid characters from and truncates extremely long filenames; only operates on the last segement of the given path. That is, if
filenameis/foo/bar/xyz, only thexyzpart of the string will be modified. - uniquify_filename(dir,basename[,ext=''[,minpadwidth=3,maxpadwidth=5]) - attempts to generate a unique filename in
dirbased onbasename. - mkdir(dir) -
mkdir -p dir - touch(file) -
touch file - rm(files...) - remove one or more files, ignoring errors. (Returns
trueif any errors are encountered,falseotherwise). - rmdir(dirs...) - recursively remove one or more directories or files, ignoring errors. (Returns
trueif any errors are encountered,falseotherwise). - read_stdin_sync([end_byte="\x04",buffer_size=512]) - synchronously read all of stdin (up to
end_byte), returning the resulting buffer - load_json_file(file, options, callback) (also just
load_json)- asynchronously read and parse a JSON file. Whenoptions.ignore_errorsis true, calls-back withnull, nullrather thanerr, null. Whenoptions.allow_commentsistrue(the default) JS-style comments are allowed. Whenoptions.strip_commentsistrue(the default) comments do NOT appear in the returned JSON object. - load_json_file_sync(file,options) - synchronously read and parse a JSON file. When
options.ignore_errorsis true, returnsnullrather than throwing an exception when the file is not found or does not contain value JSON. Whenoptions.allow_commentsistrue(the default) JS-style comments are allowed. Whenoptions.strip_commentsistrue(the default) comments do NOT appear in the returned JSON object. - load_json_stdin_sync([end_byte="\x04"[,buffer_size=512,options]]) - synchronously read and parse JSON object from stdin. When
options.ignore_errorsis true, returnsnullrather than throwing an exception. Whenoptions.allow_commentsistrue(the default) JS-style comments are allowed. Whenoptions.strip_commentsistrue(the default) comments do NOT appear in the returned JSON object. - copy_file(src,dest,callback) - copy a file from
srctodest; works across filesystems. - move_file(src,dest,callback) - move (rename) a file from
srctodest; works across filesystems.
FileUtil - MIME and File-Extension related
- get_ext(fname) / get_extension(fname) - equivalent to
path.extname, save thatfnamecan be the extension itself. (E.g., bothpath.extname('.foo')andpath.extname('foo')return''whileFileUtil.get_ext('.foo')andFileUtil.get_ext('foo')return'foo'). Specifically, returns the part offnamefollowing the final dot (.), unlessfnamecontains no dot, in which case the entirefnamevalue is returned. - strip_ext(fname) / strip_extension(fname) - returns a version of
fnamewith the file extension removed. - replace_ext(fname,ext) / replace_extension(fname,ext) - returns a version of
fnamewith the file extension changed toext. - get_mime_for_ext(ext) / get_mime_for_extension(ext) - returns the "standard" MIME type based on the extension found in
ext. (extmay be a full filename or just the extension). - get_ext_for_mime(mime) / get_extension_for_mime(mime) - returns the "standard" file extension for the given MIME type.
- get_mime_via_magic(file,callback) / get_mime_type_via_magic(file,callback) / get_file_mime_type_via_magic(file,callback) - determines MIME type of
fileby magic number (ignoring the file extension if any). - get_mime(file,callback) / get_mime_type(file,callback) / get_file_mime_type(file,callback) - determines MIME type of
fileby magic number or extension. Given a choice, the specific type is selected (e.g.,application/jsonvs.text/plain). The magic-number-based MIME type is used if the two MIME types seem equally specific. - file_is_mime(file,pattern,callback) - calls-back with
null, truewhen the MIME type offilematchespattern. - file_is_pdf(file,callback) - calls-back with
null, truewhen the MIME type offileisapplication/pdf. - get_mime_to_ext_map() / get_mime_to_extension_map() - returns the MIME-type to "standard" file-extension mapping used for the other methods.
- get_ext_to_mime_map() / get_extension_to_mime_map() - returns the file-extension to "standard" MIME-type mapping used for the other methods.
- set_mime_to_ext_map(map) / set_mime_to_extension_map(map) - sets the MIME-type to "standard" file-extension mapping used for the other methods. Extensions should NOT contain a leading dot (
.). Set tonullto restore the default mapping. - set_ext_to_mime_map(map) / set_extension_to_mime_map(map) - sets the file-extension to "standard" MIME-type mapping used for the other methods. Extensions should NOT contain a leading dot (
.). Set tonullto restore the default mapping. - add_to_mime_to_ext_map(map | mime, ext) / add_to_mime_to_ext_map(map | mime, ext) - adds a collection or a single instance of a mime-to-file-extension mapping to the currently active set.
- add_to_ext_to_mime_map(map | ext, mime) / add_to_extension_to_mime_map(map | ext, mime) - adds a collection or a single instance of a file-extension-to-mime-type mapping to the currently active set.
Note that it is not necessarily the case that get_ext_for_mime(get_mime_for_ext( EXT )) == EXT and vice-versa. See the data directory for the default mappings.
IOUtil
- pipe_to_file(readable_stream,dest,options,callback) - write a stream to a file. (
callback(err,file)). - pipe_to_buffer(readable_stream,callback) - write a stream to a buffer. (
callback(err,buffer)). - download_to_file(url,dest,options,callback) - write the contents of a URL to a file. (
callback(err,file)). - download_to_buffer(url,callback) - write the contents of a URL to a buffer. (
callback(err,buffer)). - download_to_data_uri(url,callback) - convert the contents of a URL to a data-uri. (
callback(err,uri)).
L10nUtil
- identify_locales(req) - identify a list of
[ lang, REGION ]pairs based on the given request object. - expand_locales(locales) - given a list of
[ lang, REGION ]pairs, adds[ lang, null ]to this list if otherwise missing. - identify_and_expand_locales(req) - `expand_locales(identify_locales(req))
- match_locale(accepted, available, default_value) - given a list of accepted
[ lang, REGION ]pairs and a map oflang-region: non-null, returns an acceptable key (or thedefault_value) when no matching locale is found. - load_l10n_files(dir, options, callback) - loads a set of localization files (JSON + comments) from the specified directory, returning a map of
'name-without-extension': loaded-content. When presentoptionsare options passed toFileUtil.ls, notablyrecurseandpattern(defaulting tofalseand/^.+.json$/, respectively). Note that a specificlang-REGION's attributes will inherit default values from those inlang(when set), such that ifen.jsonhas the keyfoobuten-US.jsondoes not, the returneden-usobject will contain the keyfoo. Callback signature is(err, map_of_localiation_data) - localize(localization_data, key, args...) - returns the localized value for the
sprintftemplatelocalization_data[key], passing in the optionalargsarguments when provided. Returnsnullif no matching template is found.- note that a localization entry may be a map from which one specific template will be selected according to the value of the first argument (see unit tests for details).
- make_localizer(localization_data) - returns the function of the form
fn(key, [args...])which is equivalent tolocalize(localization_data, key, [args...]).
LogUtil
- Some notes on configuration:
require('inote-util').LogUtilyields a "singleton" object with a default configuration.require('inote-util').LogUtil.initis a function that invokes theLogUtilconstructorrequire('inote-util').LogUtil.LogUtilandrequire('inote-util').LogUtil.constructorprovide direct access to theLogUtilconstructor.- Both LogUtil.init and the LogUtil.LogUtil constructor accept a single "configuration" object, a map with the following (optional) attributes:
debug- whentrueLogUtil.[t[p]]debug(...)while write toLogUtil.[t[p]]log(...); otherwiseLogUtil.debugproduces no output.prefix- when a non-nullstring is provided it will be prefixed to every log line (after the timestamp and pid identifiers, where applicable).logger- an object that defines the various underlying logging methods; by default this isconsole. Theloggermap can be used to override the default behavior by providing any of the following methods:log(...)info(...)warn(...)error(...)
- log(...), info(...), warn(...), err(...), error(...) - writes to stdout/stderr or to the equivalent method in the
loggerobject provided toLogUtil.init - tlog(...), tinfo(...), twarn(...), terr(...), terror(...) - prepends a timestamp to each log message (E.g.,
[2015-05-17T22:03:58.569Z] Hello World!) - tplog(...), tpinfo(...), tpwarn(...), tperr(...), tperror(...) - prepends a timestamp and process ID to each log message (E.g.,
[2015-05-17T22:03:58.569Z] [p:123] Hello World!) - debug(...), tdebug(...), tpdebug(...) - like
log/tlog,tplogbut only writes to the log if thedebugattribute passed to the constructor istrue.
NetUtil
- is_port_in_use(port,callback) - attempt to determine whether or not a port is currently in use
- get_unused_port(callback) - attempt to obtain an unused port
- normalize_url
NumberUtil
- round_decimal(value,digits=0) - round a number to the specified number of digits to the right of the decimal point.
- is_int(val) - returns
trueif and only ifvalis a simple integer (matching/^-?((0)|([1-9][0-9]*))$/). - to_int(val) - returns
parseInt(val)whenvalis a simple integer (matchingis_int),nullotherwise. (Compare with the default behavior ofparseInt, which returns17forparseInt("17.93 meters")). - is_float(val) - returns
trueif and only ifvalis a simple decimal value (matching/^-?((((0)|([1-9][0-9]*))(\.[0-9]+)?)|(\.[0-9]+))$/). - to_float(val) - returns
parseFloat(val)whenvalis a simple decimal value (matchingis_float),nullotherwise.
ObjectUtil
- get_json_path(json,path...) - fetches that attribute stored at the specified path
- get_funky_json_path(json,path...) - fetches that attribute stored at the specified path, handlig the
@nameandname.$attributes that some XML-to-JSON parsers produce. - deep_equal(a,b) - performs a deep comparison of the two specified objects; handles arrays, maps, strings, booleans, numbers,
nullandundefined, results are undefined for other object types; considersnull,undefinedand missing elements to be equal. - is_true_object(a) -
trueiffais a non-null, non-array object for whichtypeof a == 'object'. - diff_json(a,b) - recursively compares elements of
aandb, returning a map describing where the objects differ; handles arrays, maps, strings, booleans, numbers,nullandundefined, results are undefined for other object types; considersnull,undefinedand missing elements to be equal. Some examples:{foo:{bar:1}},{foo:{bar:1}}yieldsundefined(no difference)3,3}yieldsundefined(no difference){foo:{bar:1}},{foo:{bar:2}}yields{foo:{bar:'c'}}(value offoo.barhaschanged.{foo:{bar:null}},{foo:{bar:2}}yields{foo:{bar:'a'}}(value offoo.barwasadded.{foo:{bar:1}},{foo:{x:true}}yields{foo:{bar:'d',x:'a'}}(value offoo.barwasdeleted and value offoo.xwasadded).
- remove_null(map,recurse=false) - generates a (shallow) clone of the map or array, with
nullentries removed; whenrecurseistruethe action is repeated for each map or array-value element or attribute - remove_falsey(map,recurse=false) - generates a (shallow) clone of the map, with "falsey" entries removed (see
falsey_string); whenrecurseistruethe action is repeated for each map or array-value element or attribute - merge(maps...) - given two or more maps
aandb, creates new new map containing the union of elements from each. Ifaandbshare a key, the value inbwill overwrite the value ina. - deep_merge(maps...) - just like
mergeexcept that sub-maps are recursively merged (e.g., merging{a:{a1:1}}and{a:{a2:2}}yields{a:{a1:1,a2:2}}rather than{a:{a2:2}}). - shallow_clone(obj) - create a shallow clone of the given map or array.
- deep_clone(obj) - recursively copy the elements
objinto a new map (or array) - object_array_to_map(array,key_field,options={})) - Given a list of objects, creates a map from
elt[key_field]toeltfor eacheltin the array.options.transform- an optional function used to transform the value ofelt[key_field]before using it as the map key.options.duplicates- a string indicating how to handle duplicate keys:"overwrite"- replace the old value with the new value (the default)"stack"- create an array containing both values (in sequence)"merge"- merge the objects usingUtil.merge(old,new)"skip"- keep the old value and ignore the new one
RandomUtil
- random_bytes([count=32,encoding='hex']) - returns
countrandom bytes in the specifiedencoding. - seed_rng(seed) - returns a new
random()function with the specifiedseedvalue. - set_rn(rng = Math.random) - sets the
random()function used by theRandomUtilmethods. - random_hex([count=32,rng]) - returns
countrandom hexadecimal digits ([a-f0-9]) (using the given random number generator if provided). - random_alphanumeric([count=32,rng]) - returns
countrandom digits from the set[a-z0-9](using the given random number generator if provided). - random_alpha([count=32,rng]) - returns
countrandom digits from the set[a-z](using the given random number generator if provided). - random_numeric([count=32,rng]) - returns
countrandom digits from the set[0-9](using the given random number generator if provided). - random_Alphanumeric([count=32,rng]) - returns
countrandom digits from the set[0-9a-zA-Z](using the given random number generator if provided). - random_Alpha([count=32,rng]) - returns
countrandom digits from the set[a-zA-Z](using the given random number generator if provided). - random_ALPHA([count=32,rng]) - returns
countrandom digits from the set[A-Z](using the given random number generator if provided). - random_element(collection,rng) - returns a random element from an array, or
[key,value]pair given a map (using the given random number generator if provided). - random_value(min,max,rng) - returns a random float between
minandmax, inclusive;mindefaults to0,maxdefaults to1 - randomly_assign(id,categories) - assign the given (non-null) identifier to a randomly selected category such that (A) fgor a given collection of identifiers results will be randomly distributed among the categories and (B) for a given identifier the result will be the same every time the method is called. The
categoriesparameter is optional: when missing, identifiers will be randomly assigned to eithertrueorfalse; when an value between 0 and 1, identifiers will be assigned to eithertrueorfalse, withtrueappearing100*value% of the time; when an array, identifiers will be assigned to an element of the array with equal probability - shuffle(list) - performs an in-place shuffle of the given list
SimpleCache
- new SimpleCache({default_ttl:, default_value:, purge_interval:})
- cache.put(key, value, {ttl:})
- cache.get(key, {ignore_ttl:, default:}) / cache.set(key, {ignore_ttl:, default:})
- cache.get_put(key, value, {ttl:, ignore_ttl:, default:}) / cache.get_set(key, value, {ttl:, ignore_ttl:, default:})
- cache.clear(key)
- cache.get_clear(key, {ignore_ttl:, default:})
- cache.clear_all()
- cache.clear_matching(/regexp/)
- cache.keys({ignore_ttl:})
- cache.values({ignore_ttl:})
- cache.pairs({ignore_ttl:})
Stopwatch
A simple utility that can be used to track and report the time it takes to do some thing in your JavaScript code.
Basic Use
var SW = require('inote-util').Stopwatch;
var timer = SW.start();
// ...do something...
timer.stop();
console.log("Start Time: ",timer.start_time);
console.log("Finish Time: ",timer.finish_time);
console.log("Elapsed Time:",timer.elapsed_time);Wrapped (Synchronous)
timer = SW.time( some_method );
console.log("some_method took",timer.elapsed_time,"millis to complete.");"Cookies"
The start and time methods accept an optional map of attributes that will be bundled with the returned timer. For example:
timer = SW.start({label:"foo"});
// ...do something...
timer.stop();
console.log(timer.label," Start Time: ",timer.start_time);
console.log(timer.label,"Finish Time: ",timer.finish_time);
console.log(timer.label,"Elapsed Time:",timer.elapsed_time);StringUtil
- trim(str) - equivalent to
String.trim()save thatstrcan benull. - is_blank(str) -
truewheneverstris empty, composed entirely of whitespace,nullorundefined. - isnt_blank(str) - opposite of
is_blank() - blank_to_null(str) - given a "blank" string, returns
null. Given an object (map), removes any top-level "blank" attributes. - truncate(str,width,marker='…') - a minimally "smart" truncation that attempts to truncate a string at a word boundaries. The specified
markerwill be added if and only if the string was actually truncated. - escape_for_json(str) - escapes a (possibly
null) string for use as literal characters in a JSON string. - escape_for_regexp(str) - escapes a (possibly
null) string for use as literal characters in a regular expression. - escape_for_bash(param,esc_specials=false) - escapes a (possibly
null) string for use as command-line parameter. Whenesc_specialsisfalse(the default) parameters such as<,>,&&, etc. are not escaped. - sanitize_for_html
- json_or_null
- StringUtil.sanitize_for_sql_like
- truthy_string(str) -
trueif the given string ist,true,y,yes,on,1, etc. - falsey_string(str) -
trueif the given string isf,false,no,off,0, etc. - lpad(value,width,pad) - adds
padcharacters to the beginning ofvalueuntilvalueiswidthcharacters long. (Also accepts arrays, seeArrayUtil.lpad, which is an identical method.) - rpad(value,width,pad) - adds
padcharacters to the end ofvalueuntilvalueiswidthcharacters long. (Also accepts arrays, seeArrayUtil.rpad, which is an identical method.) - shuffle(list) - performs an in-place shuffle of the given list
Util
- get_funky_json(json,keys...) -t he call
get_funky_json(json, "foo", "bar")will returnXyzzyfor{ foo: { bar: "Xyzzy" } }and{ foo: { bar: {$:"Xyzzy" } } }and{ foo: { @bar: "Xyzzy" } }, etc. This is used to mask the differences between certain XML-to-JSON translators. This method is also aliased as gfj. - version_satisfies([version_string,]range_string) - returns
trueif the givenversion_stringsatisfies the semver criteria specified inrange_string. Whenversion_stringis omitted, the Node version (the value ofprocess.version) is used. E.g.,if(!Util.version_satisifes(">=0.12.3")) { console.error("Expected version 0.12.3 or later."); }. - slow_equals(a,b) - constant-time comparison of two buffers for equality.
- compare(a,b) - a minimally-smart comparision function (allows
null, useslocaleComparewhen available, folds case so that bothAandaappear beforeB, etc.). - field_comparator(field,use_locale_compare=false) - returns a comparator (
function(a,b)) that compares two maps on thefieldattribute. - path_comparator(path,use_locale_compare=false) - like
field_comparator, butpathmay be an array of fields that will be interpreted as nested-attributes. (E.g.,["foo","bar"]comparesa.foo.barwithb.foo.bar.) - descending_comparator(comparator) / desc_comparator(comparator) - reverses the order of the given
comparator. - composite_comparator(list) - generates a comparator that first compares elements by
list[0]then (if equal)list[1]and so on, until a non-equal comparison is found or we run out of comparators. - handle_error(err[,callback,throw_when_no_callback=true]) - if
erris notnull, invokescallback(err)orthrow erras appropriate. Returnstrueif an error was encountered,falseotherwise. (function my_callback(err,other,stuff) { if(!handle_error(err,callback)) { /* keep going */ } }) - uuid(val,generate=false) - normalize
valto all a lower-case, no-dash version of a UUID. Ifgenerateistrue, generate an new UUID when given a nullval, otherwise returnsnullin that scenario. (DEPRECATED)- As of v1.8.3, when called with no arguments
uuid()generates a UUID value, whileuuid(null)retains the original behavior.
- As of v1.8.3, when called with no arguments
- normalize_uuid(val,generate=false) - non-deprecated replacement for
uuid(val,generate). - make_uuid(val), make_uuid_v1(val), make_uuid_v4(val) - return a normalized version of the specified UUID, creating a new one if none is proivded.
- pad_uuid(val,generate=false) - normalize
valto all a lower-case, with-dashes version of a UUID. Ifgenerateistrue, generate an new UUID when given a nullval, otherwise returnsnullin that scenario. - b64e(buf,encoding='utf8') / Base64.encode(buf,encoding='utf8') - Base64 encode the given buffer.
- b64d(buf,encoding='utf8') / Base64.decode(buf,encoding='utf8') - Base64 decode the given buffer.
WebUtil
- remote_ip(req,name,default_value) - attempts to discover the proper "client IP" for the given request using various approaches.
- param(req, name, default_value) - replaces the now deprecated
req.param(name,default_value)found in Express.js.namecan also be an array of names to check. - map_to_qs(map) (also map_to_query_string(map)) - convert the given map to a string of the form
name1=value1&name2=value2&etc.for which names and values are properly URL-encoded. When a key maps to an array the key is appended multiple times (key=value1&key=value2&etc.). - append_qs(url,map) / append_qs(url,qs_fragment) / append_qs(url,name,value) (also append_query_string())
WorkQueue
WorkQueue implements a basic priority queue for asynchronous tasks.
Users may add "tasks" to the work queue, which will be asynchronously executed according to priority order.
Each task consists of:
- a function
- optionally, an array of arguments to the function
- optionally, a priority for the task
- optionally, a callback function to invoke when the task is complete
The final parameter to the task-function will always be the WorkQueue's done function. Users must call this function to indicate that the task is complete (or, optionally throw an exception).
Any arguments passed to the done function will in turn be passed to the callback function registered with the task (if any).
Example
var WorkQueue = require("inote-util").WorkQueue;
var wq = new WorkQueue();
// A task
function taskOne(a,b,cb) {
console.log("taskOne is executing. a=",a,"b=",b);
cb(1,false,a);
}
var argsOne = [ "A", "B" ];
// Another task
function taskTwo(cb) {
console.log("taskTwo is executing.");
cb(2,true,null);
}
// A callback that will be invoked after each task
function afterTask(num, exit, a) {
console.log("Task number",num,"is completed. a=",a);
if (exit) {
wq.stop_working();
}
}
wq.enqueue_task(taskOne, argsOne, afterTask);
wq.enqueue_task(taskTwo, afterTask);
wq.start_working();When run, that script generates the following output:
taskOne is executing. a= A b= B
Task number 1 is completed. a= A
taskTwo is executing.
Task number 2 is completed. a= nullEvents
The WorkQueue is also an EventEmitter, with the following events:
work-beginning - called when the queue starts processing. Arguments: the WorkQueue instance.
task-enqueued - called when a task is added to the queue. Arguments: the WorkQueue instance and the task (
{priority,method,args,callback}).task-dequeued - called when a task is selected for processing. Arguments: the WorkQueue instance and the task (
{priority,method,args,callback}).task-completed - called when a task is done (and didn't throw an uncaught exception.) Arguments: the WorkQueue instance, the task and an array of arguments passed to the
donefunction..error - called when an uncaught exception is encountered while processing the task. Arguments: the WorkQueue instance, the task and the error.
busy - called when a task is deferred because the maximum number of tasks are currently active. Arguments: the WorkQueue instance.
work-ending - called when the queue stops processing. Arguments: the WorkQueue instance.
Methods
new WorkQueue([options]) - create a new WorkQueue instance. Options:
priority- the default priority for tasks in the queue (when none is specified when the task is added). Defaults to 5. Larger numbers are executed before smaller numbers.interval- the time (in milliseconds) between "polling" the queue for new tasks to execute. Defaults to200.fuzz- a floating point value that will be used to "fuzz" the interval between polling runs. Whenfuzzis a non-zero float, a random value between-1 × fuzz × intervalandfuzz × intervalwill be added to the interval. This is used to avoid synchronization when several WorkQueues are launched with the same configuration. (E.g., when a node app that uses the WorkQueue is launched in a cluster.) Defaults to0.1.workers- the maximum number of tasks that can be active at one time. Defaults to1.
pending_task_count() - returns the number of tasks in the queue waiting to be executed.
active_task_count() - returns the number of tasks from the queue currently being executed.
enqueue_task:(method[,args][,priority][,callback]) - add a task the the queue.
start_working([options]) - start queue processing. The
optionsparameter may containintervalorfuzzattributes, which will override those provided in the construction for the duration of this processing.stop_working() - stop queue processing. Note that if a queue is started but not stopped, a function will be called roughly every
intervalmilliseconds via JavaScript'ssetIntervalmethod.
ZipUtil
- zip(wd,zipfile,inputs,callback) - creates (or appends to)
zipfile, adding the file or array of files ininputs. Whenwdis specified the action will take place relative to that directory. - unzip(wd,zipfile,dest,callback) - unzips
zipfileinto the specifieddest. - contents(zipfile,callback) - obtains a list of files within
zipfile.
Errors
- TimeoutError
- ExceptionThrownError
Installing
From Source
The source code and documentation for inote-util is available on GitHub at intellinote/inote-util. You can clone the repository via:
git clone git@github.com:intellinote/inote-utilAssuming you have node installed, you can then install the remaining dependencies by running npm install from the root repository directory.
A Makefile is provided. Run make install to install. Run make test to run the unit test suite. Run make help for a list of other useful Make targets.
From npm
inote-util is deployed as an npm module under the name inote-util. Hence you can install a pre-packaged version with the command:
npm install inote-utiland you can add it to your project as a dependency by adding a line like:
"inote-util": "latest"to the dependencies or devDependencies part of your package.json file.
Licensing
The inote-util library and related documentation are made available under an MIT License. For details, please see the file LICENSE.txt in the root directory of the repository.
How to contribute
Your contributions, bug reports and pull-requests are greatly appreciated.
We're happy to accept any help you can offer, but the following guidelines can help streamline the process for everyone.
You can report any bugs at github.com/intellinote/inote-util/issues.
- We'll be able to address the issue more easily if you can provide an demonstration of the problem you are encountering. The best format for this demonstration is a failing unit test (like those found in ./test/), but your report is welcome with or without that.
Our preferred channel for contributions or changes to the source code and documentation is as a Git "patch" or "pull-request".
If you've never submitted a pull-request, here's one way to go about it:
- Fork or clone the repository.
- Create a local branch to contain your changes (
git checkout -b my-new-branch). - Make your changes and commit them to your local repository.
- Create a pull request as described here.
If you'd rather use a private (or just non-GitHub) repository, you might find these generic instructions on creating a "patch" with Git helpful.
If you are making changes to the code please ensure that the unit test suite still passes.
If you are making changes to the code to address a bug or introduce new features, we'd greatly appreciate it if you can provide one or more unit tests that demonstrate the bug or exercise the new feature.
This repository follows the "git flow" branching convention. The
masterbranch contains snapshots of each stable release. New development occurs within thedevelopbranch. We'd prefer most pull-requests to be based off thedevelopbranch.
Please Note: We'd rather have a contribution that doesn't follow these guidelines than no contribution at all. If you are confused or put-off by any of the above, your contribution is still welcome. Feel free to contribute or comment in whatever channel works for you.
Intellinote is now BroadSoft Team-One.
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago