Initial commit
[yaffs-website] / node_modules / hoek / README.md
1 ![hoek Logo](https://raw.github.com/hapijs/hoek/master/images/hoek.png)
2
3 Utility methods for the hapi ecosystem. This module is not intended to solve every problem for everyone, but rather as a central place to store hapi-specific methods. If you're looking for a general purpose utility module, check out [lodash](https://github.com/lodash/lodash) or [underscore](https://github.com/jashkenas/underscore).
4
5 [![Build Status](https://secure.travis-ci.org/hapijs/hoek.svg)](http://travis-ci.org/hapijs/hoek)
6
7 Lead Maintainer: [Nathan LaFreniere](https://github.com/nlf)
8
9 # Table of Contents
10
11 * [Introduction](#introduction "Introduction")
12 * [Object](#object "Object")
13   * [clone](#cloneobj "clone")
14   * [cloneWithShallow](#clonewithshallowobj-keys "cloneWithShallow")
15   * [merge](#mergetarget-source-isnulloverride-ismergearrays "merge")
16   * [applyToDefaults](#applytodefaultsdefaults-options-isnulloverride "applyToDefaults")
17   * [applyToDefaultsWithShallow](#applytodefaultswithshallowdefaults-options-keys "applyToDefaultsWithShallow")
18   * [deepEqual](#deepequala-b "deepEqual")
19   * [unique](#uniquearray-key "unique")
20   * [mapToObject](#maptoobjectarray-key "mapToObject")
21   * [intersect](#intersectarray1-array2 "intersect")
22   * [contain](#containref-values-options "contain")
23   * [flatten](#flattenarray-target "flatten")
24   * [reach](#reachobj-chain-options "reach")
25   * [reachTemplate](#reachtemplateobj-template-options "reachTemplate")
26   * [transform](#transformobj-transform-options "transform")
27   * [shallow](#shallowobj "shallow")
28   * [stringify](#stringifyobj "stringify")
29 * [Timer](#timer "Timer")
30 * [Bench](#bench "Bench")
31 * [Binary Encoding/Decoding](#binary-encodingdecoding "Binary Encoding/Decoding")
32   * [base64urlEncode](#base64urlencodevalue "binary64urlEncode")
33   * [base64urlDecode](#base64urldecodevalue "binary64urlDecode")
34 * [Escaping Characters](#escaping-characters "Escaping Characters")
35   * [escapeHtml](#escapehtmlstring "escapeHtml")
36   * [escapeHeaderAttribute](#escapeheaderattributeattribute "escapeHeaderAttribute")
37   * [escapeRegex](#escaperegexstring "escapeRegex")
38 * [Errors](#errors "Errors")
39   * [assert](#assertcondition-message "assert")
40   * [abort](#abortmessage "abort")
41   * [displayStack](#displaystackslice "displayStack")
42   * [callStack](#callstackslice "callStack")
43 * [Function](#function "Function")
44   * [nextTick](#nexttickfn "nextTick")
45   * [once](#oncefn "once")
46   * [ignore](#ignore "ignore")
47 * [Miscellaneous](#miscellaneous "Miscellaneous")
48   * [uniqueFilename](#uniquefilenamepath-extension "uniqueFilename")
49   * [isAbsolutePath](#isabsolutepathpath-platform "isAbsolutePath")
50   * [isInteger](#isintegervalue "isInteger")
51
52
53
54 # Introduction
55
56 The *Hoek* library contains some common functions used within the hapi ecosystem. It comes with useful methods for Arrays (clone, merge, applyToDefaults), Objects (removeKeys, copy), Asserting and more.
57
58 For example, to use Hoek to set configuration with default options:
59 ```javascript
60 var Hoek = require('hoek');
61
62 var default = {url : "www.github.com", port : "8000", debug : true};
63
64 var config = Hoek.applyToDefaults(default, {port : "3000", admin : true});
65
66 // In this case, config would be { url: 'www.github.com', port: '3000', debug: true, admin: true }
67 ```
68
69 Under each of the sections (such as Array), there are subsections which correspond to Hoek methods. Each subsection will explain how to use the corresponding method. In each js excerpt below, the `var Hoek = require('hoek');` is omitted for brevity.
70
71 ## Object
72
73 Hoek provides several helpful methods for objects and arrays.
74
75 ### clone(obj)
76
77 This method is used to clone an object or an array. A *deep copy* is made (duplicates everything, including values that are objects, as well as non-enumerable properties).
78
79 ```javascript
80
81 var nestedObj = {
82         w: /^something$/ig,
83         x: {
84             a: [1, 2, 3],
85             b: 123456,
86             c: new Date()
87         },
88         y: 'y',
89         z: new Date()
90     };
91
92 var copy = Hoek.clone(nestedObj);
93
94 copy.x.b = 100;
95
96 console.log(copy.y);        // results in 'y'
97 console.log(nestedObj.x.b); // results in 123456
98 console.log(copy.x.b);      // results in 100
99 ```
100
101 ### cloneWithShallow(obj, keys)
102 keys is an array of key names to shallow copy
103
104 This method is also used to clone an object or array, however any keys listed in the `keys` array are shallow copied while those not listed are deep copied.
105
106 ```javascript
107
108 var nestedObj = {
109         w: /^something$/ig,
110         x: {
111             a: [1, 2, 3],
112             b: 123456,
113             c: new Date()
114         },
115         y: 'y',
116         z: new Date()
117     };
118
119 var copy = Hoek.cloneWithShallow(nestedObj, ['x']);
120
121 copy.x.b = 100;
122
123 console.log(copy.y);        // results in 'y'
124 console.log(nestedObj.x.b); // results in 100
125 console.log(copy.x.b);      // results in 100
126 ```
127
128 ### merge(target, source, isNullOverride, isMergeArrays)
129 isNullOverride, isMergeArrays default to true
130
131 Merge all the properties of source into target, source wins in conflict, and by default null and undefined from source are applied.
132 Merge is destructive where the target is modified. For non destructive merge, use `applyToDefaults`.
133
134
135 ```javascript
136
137 var target = {a: 1, b : 2};
138 var source = {a: 0, c: 5};
139 var source2 = {a: null, c: 5};
140
141 Hoek.merge(target, source);         // results in {a: 0, b: 2, c: 5}
142 Hoek.merge(target, source2);        // results in {a: null, b: 2, c: 5}
143 Hoek.merge(target, source2, false); // results in {a: 1, b: 2, c: 5}
144
145 var targetArray = [1, 2, 3];
146 var sourceArray = [4, 5];
147
148 Hoek.merge(targetArray, sourceArray);              // results in [1, 2, 3, 4, 5]
149 Hoek.merge(targetArray, sourceArray, true, false); // results in [4, 5]
150 ```
151
152 ### applyToDefaults(defaults, options, isNullOverride)
153 isNullOverride defaults to false
154
155 Apply options to a copy of the defaults
156
157 ```javascript
158
159 var defaults = { host: "localhost", port: 8000 };
160 var options = { port: 8080 };
161
162 var config = Hoek.applyToDefaults(defaults, options); // results in { host: "localhost", port: 8080 }
163 ```
164
165 Apply options with a null value to a copy of the defaults
166
167 ```javascript
168
169 var defaults = { host: "localhost", port: 8000 };
170 var options = { host: null, port: 8080 };
171
172 var config = Hoek.applyToDefaults(defaults, options, true); // results in { host: null, port: 8080 }
173 ```
174
175 ### applyToDefaultsWithShallow(defaults, options, keys)
176 keys is an array of key names to shallow copy
177
178 Apply options to a copy of the defaults. Keys specified in the last parameter are shallow copied from options instead of merged.
179
180 ```javascript
181
182 var defaults = {
183         server: {
184             host: "localhost",
185             port: 8000
186         },
187         name: 'example'
188     };
189
190 var options = { server: { port: 8080 } };
191
192 var config = Hoek.applyToDefaultsWithShallow(defaults, options, ['server']); // results in { server: { port: 8080 }, name: 'example' }
193 ```
194
195 ### deepEqual(b, a, [options])
196
197 Performs a deep comparison of the two values including support for circular dependencies, prototype, and properties. To skip prototype comparisons, use `options.prototype = false`
198
199 ```javascript
200 Hoek.deepEqual({ a: [1, 2], b: 'string', c: { d: true } }, { a: [1, 2], b: 'string', c: { d: true } }); //results in true
201 Hoek.deepEqual(Object.create(null), {}, { prototype: false }); //results in true
202 Hoek.deepEqual(Object.create(null), {}); //results in false
203 ```
204
205 ### unique(array, key)
206
207 Remove duplicate items from Array
208
209 ```javascript
210
211 var array = [1, 2, 2, 3, 3, 4, 5, 6];
212
213 var newArray = Hoek.unique(array);    // results in [1,2,3,4,5,6]
214
215 array = [{id: 1}, {id: 1}, {id: 2}];
216
217 newArray = Hoek.unique(array, "id");  // results in [{id: 1}, {id: 2}]
218 ```
219
220 ### mapToObject(array, key)
221
222 Convert an Array into an Object
223
224 ```javascript
225
226 var array = [1,2,3];
227 var newObject = Hoek.mapToObject(array);   // results in [{"1": true}, {"2": true}, {"3": true}]
228
229 array = [{id: 1}, {id: 2}];
230 newObject = Hoek.mapToObject(array, "id"); // results in [{"id": 1}, {"id": 2}]
231 ```
232
233 ### intersect(array1, array2)
234
235 Find the common unique items in two arrays
236
237 ```javascript
238
239 var array1 = [1, 2, 3];
240 var array2 = [1, 4, 5];
241
242 var newArray = Hoek.intersect(array1, array2); // results in [1]
243 ```
244
245 ### contain(ref, values, [options])
246
247 Tests if the reference value contains the provided values where:
248 - `ref` - the reference string, array, or object.
249 - `values` - a single or array of values to find within the `ref` value. If `ref` is an object, `values` can be a key name,
250   an array of key names, or an object with key-value pairs to compare.
251 - `options` - an optional object with the following optional settings:
252     - `deep` - if `true`, performed a deep comparison of the values.
253     - `once` - if `true`, allows only one occurrence of each value.
254     - `only` - if `true`, does not allow values not explicitly listed.
255     - `part` - if `true`, allows partial match of the values (at least one must always match).
256
257 Note: comparing a string to overlapping values will result in failed comparison (e.g. `contain('abc', ['ab', 'bc'])`).
258 Also, if an object key's value does not match the provided value, `false` is returned even when `part` is specified.
259
260 ```javascript
261 Hoek.contain('aaa', 'a', { only: true });                                                       // true
262 Hoek.contain([{ a: 1 }], [{ a: 1 }], { deep: true });                           // true
263 Hoek.contain([1, 2, 2], [1, 2], { once: true });                                        // false
264 Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 1, d: 4 }, { part: true }); // true
265 ```
266
267 ### flatten(array, [target])
268
269 Flatten an array
270
271 ```javascript
272
273 var array = [1, [2, 3]];
274
275 var flattenedArray = Hoek.flatten(array); // results in [1, 2, 3]
276
277 array = [1, [2, 3]];
278 target = [4, [5]];
279
280 flattenedArray = Hoek.flatten(array, target); // results in [4, [5], 1, 2, 3]
281 ```
282
283 ### reach(obj, chain, [options])
284
285 Converts an object key chain string to reference
286
287 - `options` - optional settings
288     - `separator` - string to split chain path on, defaults to '.'
289     - `default` - value to return if the path or value is not present, default is `undefined`
290     - `strict` - if `true`, will throw an error on missing member, default is `false`
291     - `functions` - if `true` allow traversing functions for properties. `false` will throw an error if a function is part of the chain.
292
293 A chain including negative numbers will work like negative indices on an
294 array.
295
296 If chain is `null`, `undefined` or `false`, the object itself will be returned.
297
298 ```javascript
299
300 var chain = 'a.b.c';
301 var obj = {a : {b : { c : 1}}};
302
303 Hoek.reach(obj, chain); // returns 1
304
305 var chain = 'a.b.-1';
306 var obj = {a : {b : [2,3,6]}};
307
308 Hoek.reach(obj, chain); // returns 6
309 ```
310
311 ### reachTemplate(obj, template, [options])
312
313 Replaces string parameters (`{name}`) with their corresponding object key values by applying the
314 (`reach()`)[#reachobj-chain-options] method where:
315
316 - `obj` - the context object used for key lookup.
317 - `template` - a string containing `{}` parameters.
318 - `options` - optional (`reach()`)[#reachobj-chain-options] options.
319
320 ```javascript
321
322 var chain = 'a.b.c';
323 var obj = {a : {b : { c : 1}}};
324
325 Hoek.reachTemplate(obj, '1+{a.b.c}=2'); // returns '1+1=2'
326 ```
327
328 ### transform(obj, transform, [options])
329
330 Transforms an existing object into a new one based on the supplied `obj` and `transform` map. `options` are the same as the `reach` options. The first argument can also be an array of objects. In that case the method will return an array of transformed objects.
331
332 ```javascript
333 var source = {
334     address: {
335         one: '123 main street',
336         two: 'PO Box 1234'
337     },
338     title: 'Warehouse',
339     state: 'CA'
340 };
341
342 var result = Hoek.transform(source, {
343     'person.address.lineOne': 'address.one',
344     'person.address.lineTwo': 'address.two',
345     'title': 'title',
346     'person.address.region': 'state'
347 });
348 // Results in
349 // {
350 //     person: {
351 //         address: {
352 //             lineOne: '123 main street',
353 //             lineTwo: 'PO Box 1234',
354 //             region: 'CA'
355 //         }
356 //     },
357 //     title: 'Warehouse'
358 // }
359 ```
360
361 ### shallow(obj)
362
363 Performs a shallow copy by copying the references of all the top level children where:
364 - `obj` - the object to be copied.
365
366 ```javascript
367 var shallow = Hoek.shallow({ a: { b: 1 } });
368 ```
369
370 ### stringify(obj)
371
372 Converts an object to string using the built-in `JSON.stringify()` method with the difference that any errors are caught
373 and reported back in the form of the returned string. Used as a shortcut for displaying information to the console (e.g. in
374 error message) without the need to worry about invalid conversion.
375
376 ```javascript
377 var a = {};
378 a.b = a;
379 Hoek.stringify(a);              // Returns '[Cannot display object: Converting circular structure to JSON]'
380 ```
381
382 # Timer
383
384 A Timer object. Initializing a new timer object sets the ts to the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC.
385
386 ```javascript
387
388 var timerObj = new Hoek.Timer();
389 console.log("Time is now: " + timerObj.ts);
390 console.log("Elapsed time from initialization: " + timerObj.elapsed() + 'milliseconds');
391 ```
392
393
394 # Bench
395
396 Same as Timer with the exception that `ts` stores the internal node clock which is not related to `Date.now()` and cannot be used to display
397 human-readable timestamps. More accurate for benchmarking or internal timers.
398
399 # Binary Encoding/Decoding
400
401 ### base64urlEncode(value)
402
403 Encodes value in Base64 or URL encoding
404
405 ### base64urlDecode(value)
406
407 Decodes data in Base64 or URL encoding.
408 # Escaping Characters
409
410 Hoek provides convenient methods for escaping html characters. The escaped characters are as followed:
411
412 ```javascript
413
414 internals.htmlEscaped = {
415     '&': '&',
416     '<': '&lt;',
417     '>': '&gt;',
418     '"': '&quot;',
419     "'": '&#x27;',
420     '`': '&#x60;'
421 };
422 ```
423
424 ### escapeHtml(string)
425
426 ```javascript
427
428 var string = '<html> hey </html>';
429 var escapedString = Hoek.escapeHtml(string); // returns &lt;html&gt; hey &lt;/html&gt;
430 ```
431
432 ### escapeHeaderAttribute(attribute)
433
434 Escape attribute value for use in HTTP header
435
436 ```javascript
437
438 var a = Hoek.escapeHeaderAttribute('I said "go w\\o me"');  //returns I said \"go w\\o me\"
439 ```
440
441
442 ### escapeRegex(string)
443
444 Escape string for Regex construction
445
446 ```javascript
447
448 var a = Hoek.escapeRegex('4^f$s.4*5+-_?%=#!:@|~\\/`"(>)[<]d{}s,');  // returns 4\^f\$s\.4\*5\+\-_\?%\=#\!\:@\|~\\\/`"\(>\)\[<\]d\{\}s\,
449 ```
450
451 # Errors
452
453 ### assert(condition, message)
454
455 ```javascript
456
457 var a = 1, b = 2;
458
459 Hoek.assert(a === b, 'a should equal b');  // Throws 'a should equal b'
460 ```
461
462 Note that you may also pass an already created Error object as the second parameter, and `assert` will throw that object.
463
464 ```javascript
465
466 var a = 1, b = 2;
467
468 Hoek.assert(a === b, new Error('a should equal b')); // Throws the given error object
469 ```
470
471 ### abort(message)
472
473 First checks if `process.env.NODE_ENV === 'test'`, and if so, throws error message. Otherwise,
474 displays most recent stack and then exits process.
475
476
477
478 ### displayStack(slice)
479
480 Displays the trace stack
481
482 ```javascript
483
484 var stack = Hoek.displayStack();
485 console.log(stack); // returns something like:
486
487 [ 'null (/Users/user/Desktop/hoek/test.js:4:18)',
488   'Module._compile (module.js:449:26)',
489   'Module._extensions..js (module.js:467:10)',
490   'Module.load (module.js:356:32)',
491   'Module._load (module.js:312:12)',
492   'Module.runMain (module.js:492:10)',
493   'startup.processNextTick.process._tickCallback (node.js:244:9)' ]
494 ```
495
496 ### callStack(slice)
497
498 Returns a trace stack array.
499
500 ```javascript
501
502 var stack = Hoek.callStack();
503 console.log(stack);  // returns something like:
504
505 [ [ '/Users/user/Desktop/hoek/test.js', 4, 18, null, false ],
506   [ 'module.js', 449, 26, 'Module._compile', false ],
507   [ 'module.js', 467, 10, 'Module._extensions..js', false ],
508   [ 'module.js', 356, 32, 'Module.load', false ],
509   [ 'module.js', 312, 12, 'Module._load', false ],
510   [ 'module.js', 492, 10, 'Module.runMain', false ],
511   [ 'node.js',
512     244,
513     9,
514     'startup.processNextTick.process._tickCallback',
515     false ] ]
516 ```
517
518 ## Function
519
520 ### nextTick(fn)
521
522 Returns a new function that wraps `fn` in `process.nextTick`.
523
524 ```javascript
525
526 var myFn = function () {
527     console.log('Do this later');
528 };
529
530 var nextFn = Hoek.nextTick(myFn);
531
532 nextFn();
533 console.log('Do this first');
534
535 // Results in:
536 //
537 // Do this first
538 // Do this later
539 ```
540
541 ### once(fn)
542
543 Returns a new function that can be run multiple times, but makes sure `fn` is only run once.
544
545 ```javascript
546
547 var myFn = function () {
548     console.log('Ran myFn');
549 };
550
551 var onceFn = Hoek.once(myFn);
552 onceFn(); // results in "Ran myFn"
553 onceFn(); // results in undefined
554 ```
555
556 ### ignore
557
558 A simple no-op function. It does nothing at all.
559
560 ## Miscellaneous
561
562 ### uniqueFilename(path, extension)
563 `path` to prepend with the randomly generated file name. `extension` is the optional file extension, defaults to `''`.
564
565 Returns a randomly generated file name at the specified `path`. The result is a fully resolved path to a file.
566
567 ```javascript
568 var result = Hoek.uniqueFilename('./test/modules', 'txt'); // results in "full/path/test/modules/{random}.txt"
569 ```
570
571 ### isAbsolutePath(path, [platform])
572
573 Determines whether `path` is an absolute path. Returns `true` or `false`.
574
575 - `path` - A file path to test for whether it is absolute or not.
576 - `platform` - An optional parameter used for specifying the platform. Defaults to `process.platform`.
577
578 ### isInteger(value)
579
580 Check `value` to see if it is an integer.  Returns true/false.
581
582 ```javascript
583 var result = Hoek.isInteger('23')
584 ```