From e647ea13dcb795f31f04224121478a41efe2ecac Mon Sep 17 00:00:00 2001 From: Paolo Memoli Date: Tue, 2 Jun 2015 01:06:20 +0200 Subject: [PATCH 01/25] added frontend and bluetooth modules --- routes.js => backend.js | 73 +- bluetooth.js | 54 + frontend.js | 8 + images/banjo.png | Bin 65215 -> 0 bytes images/headers.png | Bin 177568 -> 0 bytes images/products.png | Bin 70351 -> 0 bytes node_modules/.bin/hapi | 1 - node_modules/handlebars/.jshintrc | 52 - node_modules/handlebars/.npmignore | 15 + node_modules/handlebars/.rspec | 1 - node_modules/handlebars/LICENSE | 2 +- node_modules/handlebars/README.markdown | 185 +- node_modules/handlebars/bin/handlebars | 162 +- node_modules/handlebars/bower.json | 9 - node_modules/handlebars/global-test.js | 18 - node_modules/handlebars/global.js | 4 - .../handlebars/handlebars-source.gemspec | 21 - node_modules/handlebars/handlebars.js.nuspec | 17 - node_modules/handlebars/min.sh | 11 - .../handlebars/node_modules/optimist/index.js | 201 +- .../node_modules/optimist/package.json | 11 +- .../node_modules/optimist/readme.markdown | 26 + .../node_modules/source-map/.npmignore | 2 - .../node_modules/source-map/.travis.yml | 4 - .../node_modules/source-map/CHANGELOG.md | 194 - .../uglify-js/node_modules/source-map/LICENSE | 28 - .../source-map/Makefile.dryice.js | 166 - .../node_modules/source-map/README.md | 475 --- .../source-map/node_modules/amdefine/LICENSE | 58 - .../node_modules/amdefine/README.md | 171 - .../node_modules/amdefine/amdefine.js | 299 -- .../node_modules/amdefine/intercept.js | 36 - .../node_modules/amdefine/package.json | 37 - .../node_modules/source-map/package.json | 186 - .../node_modules/source-map/test/run-tests.js | 62 - .../source-map/test/source-map/test-api.js | 26 - .../test/source-map/test-array-set.js | 104 - .../test/source-map/test-base64-vlq.js | 23 - .../source-map/test/source-map/test-base64.js | 35 - .../test/source-map/test-binary-search.js | 54 - .../test/source-map/test-dog-fooding.js | 84 - .../source-map/test-source-map-consumer.js | 702 ---- .../source-map/test-source-map-generator.js | 679 ---- .../test/source-map/test-source-node.js | 612 ---- .../source-map/test/source-map/test-util.js | 216 -- .../source-map/test/source-map/util.js | 192 - node_modules/handlebars/package.json | 92 +- node_modules/handlebars/release-notes.md | 287 +- node_modules/handlebars/test.js | 20 - node_modules/hapi/.gitattributes | 10 - node_modules/hapi/.npmignore | 4 +- node_modules/hapi/.travis.yml | 8 +- node_modules/hapi/CONTRIBUTING.md | 6 +- node_modules/hapi/LICENSE | 20 +- node_modules/hapi/Makefile | 9 - node_modules/hapi/README.md | 70 +- node_modules/hapi/bin/hapi | 123 - node_modules/hapi/docs/Plugins.md | 18 - node_modules/hapi/docs/Reference.md | 3206 ----------------- node_modules/hapi/docs/Style.md | 678 ---- node_modules/hapi/examples/auth.js | 102 - node_modules/hapi/examples/cache.js | 64 - node_modules/hapi/examples/composer.json | 26 - node_modules/hapi/examples/cookie.js | 94 - .../hapi/examples/directory/index.html | 12 - .../hapi/examples/directory/server.js | 32 - node_modules/hapi/examples/errors.js | 42 - node_modules/hapi/examples/extensions.js | 59 - node_modules/hapi/examples/favicon.ico | Bin 1150 -> 0 bytes node_modules/hapi/examples/favicon.js | 24 - node_modules/hapi/examples/file/index.html | 12 - node_modules/hapi/examples/file/server.js | 31 - node_modules/hapi/examples/files.js | 31 - node_modules/hapi/examples/helpers.js | 63 - node_modules/hapi/examples/injection.js | 37 - node_modules/hapi/examples/jsonp.js | 30 - node_modules/hapi/examples/prerequisites.js | 74 - node_modules/hapi/examples/proxy.js | 26 - node_modules/hapi/examples/socketio.js | 38 - node_modules/hapi/examples/stream.js | 35 - node_modules/hapi/examples/tails.js | 47 - node_modules/hapi/examples/validation.js | 69 - .../examples/views/cms/_pages/.placeholder | 0 .../hapi/examples/views/cms/_pages/Test | 1 - node_modules/hapi/examples/views/cms/pages.js | 65 - .../hapi/examples/views/cms/server.js | 81 - .../hapi/examples/views/cms/views/create.html | 25 - .../hapi/examples/views/cms/views/edit.html | 25 - .../hapi/examples/views/cms/views/index.html | 34 - .../hapi/examples/views/cms/views/layout.html | 25 - .../hapi/examples/views/cms/views/page.html | 4 - .../views/cms/views/partials/footer.html | 1 - .../views/cms/views/partials/nav.html | 21 - .../hapi/examples/views/handlebars/basic.js | 35 - .../hapi/examples/views/handlebars/layout.js | 37 - .../examples/views/handlebars/partials.js | 37 - .../handlebars/templates/basic/index.html | 11 - .../views/handlebars/templates/layout.html | 11 - .../templates/withLayout/index.html | 3 - .../templates/withPartials/footer.html | 3 - .../templates/withPartials/header.html | 3 - .../templates/withPartials/index.html | 13 - .../hapi/examples/views/jade/index.js | 47 - .../examples/views/jade/templates/about.jade | 5 - .../views/jade/templates/includes/foot.jade | 2 - .../views/jade/templates/includes/head.jade | 2 - .../examples/views/jade/templates/index.jade | 5 - .../examples/views/jade/templates/layout.jade | 5 - .../hapi/examples/views/mixed/index.js | 45 - .../views/mixed/templates/handlebars.html | 6 - .../examples/views/mixed/templates/index.jade | 4 - node_modules/hapi/index.js | 1 - node_modules/hapi/lab_runner.js | 2 - node_modules/hapi/node_modules/.bin/semver | 1 - node_modules/hapi/node_modules/async/LICENSE | 19 - .../hapi/node_modules/async/README.md | 1425 -------- .../hapi/node_modules/async/component.json | 11 - .../hapi/node_modules/async/package.json | 61 - .../hapi/node_modules/boom/.travis.yml | 2 + node_modules/hapi/node_modules/boom/LICENSE | 14 +- node_modules/hapi/node_modules/boom/Makefile | 11 - node_modules/hapi/node_modules/boom/README.md | 583 ++- .../hapi/node_modules/boom/package.json | 61 +- .../hapi/node_modules/boom/test/index.js | 676 +++- .../hapi/node_modules/catbox/.travis.yml | 6 +- node_modules/hapi/node_modules/catbox/LICENSE | 14 +- .../hapi/node_modules/catbox/Makefile | 8 +- .../hapi/node_modules/catbox/README.md | 124 +- .../node_modules/catbox/examples/mongo.js | 76 - .../node_modules/catbox/examples/policy.js | 23 +- .../node_modules/catbox/examples/redis.js | 76 - .../hapi/node_modules/catbox/package.json | 64 +- .../hapi/node_modules/catbox/test/client.js | 442 ++- .../hapi/node_modules/catbox/test/common.js | 324 -- .../hapi/node_modules/catbox/test/defaults.js | 87 - .../hapi/node_modules/catbox/test/helper.js | 39 - .../hapi/node_modules/catbox/test/memory.js | 276 -- .../hapi/node_modules/catbox/test/mongo.js | 755 ---- .../hapi/node_modules/catbox/test/policy.js | 1798 ++++++--- .../hapi/node_modules/catbox/test/redis.js | 426 --- .../hapi/node_modules/cryptiles/LICENSE | 14 +- .../hapi/node_modules/cryptiles/Makefile | 10 +- .../hapi/node_modules/cryptiles/README.md | 10 +- .../hapi/node_modules/cryptiles/package.json | 43 +- .../hapi/node_modules/cryptiles/test/index.js | 15 +- .../hapi/node_modules/hawk/.npmignore | 20 - .../hapi/node_modules/hawk/.travis.yml | 5 - node_modules/hapi/node_modules/hawk/LICENSE | 24 - node_modules/hapi/node_modules/hawk/Makefile | 8 - node_modules/hapi/node_modules/hawk/README.md | 625 ---- .../hapi/node_modules/hawk/component.json | 19 - .../hapi/node_modules/hawk/example/usage.js | 78 - .../hapi/node_modules/hawk/images/hawk.png | Bin 6945 -> 0 bytes .../hapi/node_modules/hawk/images/logo.png | Bin 71732 -> 0 bytes node_modules/hapi/node_modules/hawk/index.js | 1 - .../hawk/node_modules/boom/.npmignore | 18 - .../hawk/node_modules/boom/.travis.yml | 5 - .../hawk/node_modules/boom/AUTHORS | 3 - .../hawk/node_modules/boom/LICENSE | 24 - .../hawk/node_modules/boom/Makefile | 9 - .../hawk/node_modules/boom/README.md | 6 - .../hawk/node_modules/boom/images/boom.png | Bin 29479 -> 0 bytes .../hawk/node_modules/boom/index.js | 1 - .../hawk/node_modules/boom/package.json | 75 - .../hawk/node_modules/boom/test/index.js | 529 --- .../hawk/node_modules/cryptiles/.npmignore | 18 - .../hawk/node_modules/cryptiles/.travis.yml | 5 - .../hawk/node_modules/cryptiles/LICENSE | 24 - .../hawk/node_modules/cryptiles/Makefile | 9 - .../hawk/node_modules/cryptiles/README.md | 6 - .../hawk/node_modules/cryptiles/index.js | 1 - .../hawk/node_modules/cryptiles/package.json | 62 - .../hawk/node_modules/cryptiles/test/index.js | 101 - .../hawk/node_modules/hoek/.npmignore | 18 - .../hawk/node_modules/hoek/.travis.yml | 5 - .../hawk/node_modules/hoek/AUTHORS | 3 - .../hawk/node_modules/hoek/LICENSE | 33 - .../hawk/node_modules/hoek/Makefile | 8 - .../hawk/node_modules/hoek/README.md | 426 --- .../hawk/node_modules/hoek/images/hoek.png | Bin 37939 -> 0 bytes .../hawk/node_modules/hoek/index.js | 1 - .../hawk/node_modules/hoek/package.json | 77 - .../hawk/node_modules/hoek/test/escaper.js | 86 - .../hawk/node_modules/hoek/test/index.js | 1322 ------- .../node_modules/hoek/test/modules/test1.js | 1 - .../node_modules/hoek/test/modules/test2.js | 1 - .../node_modules/hoek/test/modules/test3.js | 1 - .../hawk/node_modules/sntp/.npmignore | 18 - .../hawk/node_modules/sntp/.travis.yml | 5 - .../hawk/node_modules/sntp/LICENSE | 28 - .../hawk/node_modules/sntp/Makefile | 9 - .../hawk/node_modules/sntp/README.md | 68 - .../hawk/node_modules/sntp/examples/offset.js | 16 - .../hawk/node_modules/sntp/examples/time.js | 25 - .../hawk/node_modules/sntp/index.js | 1 - .../sntp/node_modules/hoek/.npmignore | 18 - .../sntp/node_modules/hoek/.travis.yml | 7 - .../sntp/node_modules/hoek/CONTRIBUTING.md | 1 - .../sntp/node_modules/hoek/LICENSE | 31 - .../sntp/node_modules/hoek/Makefile | 8 - .../sntp/node_modules/hoek/README.md | 574 --- .../sntp/node_modules/hoek/images/hoek.png | Bin 37939 -> 0 bytes .../sntp/node_modules/hoek/index.js | 1 - .../sntp/node_modules/hoek/package.json | 60 - .../sntp/node_modules/hoek/test/escaper.js | 88 - .../sntp/node_modules/hoek/test/index.js | 2425 ------------- .../node_modules/hoek/test/modules/ignore.txt | 0 .../node_modules/hoek/test/modules/test1.js | 1 - .../node_modules/hoek/test/modules/test2.js | 1 - .../node_modules/hoek/test/modules/test3.js | 1 - .../hawk/node_modules/sntp/package.json | 65 - .../hawk/node_modules/sntp/test/index.js | 435 --- .../hapi/node_modules/hawk/package.json | 67 - .../hapi/node_modules/hawk/test/browser.js | 817 ----- .../hapi/node_modules/hawk/test/client.js | 206 -- .../hapi/node_modules/hawk/test/crypto.js | 86 - .../hapi/node_modules/hawk/test/index.js | 316 -- .../hapi/node_modules/hawk/test/message.js | 246 -- .../hapi/node_modules/hawk/test/readme.js | 98 - .../hapi/node_modules/hawk/test/server.js | 686 ---- .../hapi/node_modules/hawk/test/uri.js | 456 --- .../hapi/node_modules/hawk/test/utils.js | 120 - .../hapi/node_modules/hoek/.travis.yml | 2 + node_modules/hapi/node_modules/hoek/LICENSE | 20 +- node_modules/hapi/node_modules/hoek/Makefile | 12 +- node_modules/hapi/node_modules/hoek/README.md | 412 ++- node_modules/hapi/node_modules/hoek/index.js | 2 +- .../hapi/node_modules/hoek/package.json | 63 +- .../hapi/node_modules/hoek/test/escaper.js | 104 +- .../hapi/node_modules/hoek/test/index.js | 2791 ++++++++++---- node_modules/hapi/node_modules/iron/LICENSE | 14 +- node_modules/hapi/node_modules/iron/Makefile | 6 +- node_modules/hapi/node_modules/iron/README.md | 25 +- .../hapi/node_modules/iron/package.json | 38 +- .../hapi/node_modules/iron/test/index.js | 163 +- node_modules/hapi/node_modules/joi/.npmignore | 2 + .../hapi/node_modules/joi/.travis.yml | 21 +- node_modules/hapi/node_modules/joi/LICENSE | 14 +- node_modules/hapi/node_modules/joi/Makefile | 8 - node_modules/hapi/node_modules/joi/README.md | 1493 ++++++-- node_modules/hapi/node_modules/joi/index.js | 2 +- .../node_modules/joi/languages/en-US.json | 12 - .../hapi/node_modules/joi/package.json | 71 +- .../hapi/node_modules/joi/test/index.js | 1710 +++++++-- .../hapi/node_modules/joi/test/messages.js | 64 - .../hapi/node_modules/joi/test/set.js | 117 - .../node_modules/joi/test/support/meta.js | 30 - .../hapi/node_modules/joi/test/types/any.js | 79 - .../hapi/node_modules/joi/test/types/array.js | 227 -- .../hapi/node_modules/joi/test/types/base.js | 294 -- .../node_modules/joi/test/types/boolean.js | 133 - .../node_modules/joi/test/types/function.js | 47 - .../hapi/node_modules/joi/test/types/index.js | 103 - .../node_modules/joi/test/types/number.js | 424 --- .../node_modules/joi/test/types/object.js | 158 - .../node_modules/joi/test/types/string.js | 910 ----- .../hapi/node_modules/lru-cache/.npmignore | 1 - .../hapi/node_modules/lru-cache/AUTHORS | 8 - .../hapi/node_modules/lru-cache/LICENSE | 23 - .../hapi/node_modules/lru-cache/README.md | 97 - .../hapi/node_modules/lru-cache/bench.js | 25 - .../hapi/node_modules/lru-cache/package.json | 63 - .../hapi/node_modules/lru-cache/test/basic.js | 329 -- .../node_modules/lru-cache/test/foreach.js | 52 - .../lru-cache/test/memory-leak.js | 50 - node_modules/hapi/node_modules/mime/LICENSE | 19 - node_modules/hapi/node_modules/mime/README.md | 66 - node_modules/hapi/node_modules/mime/mime.js | 114 - .../hapi/node_modules/mime/package.json | 59 - node_modules/hapi/node_modules/mime/test.js | 84 - .../hapi/node_modules/mime/types/mime.types | 1588 -------- .../hapi/node_modules/mime/types/node.types | 77 - .../hapi/node_modules/multiparty/.jshintrc | 70 - .../hapi/node_modules/multiparty/.npmignore | 1 - .../hapi/node_modules/multiparty/.travis.yml | 5 - .../hapi/node_modules/multiparty/CHANGELOG.md | 181 - .../hapi/node_modules/multiparty/LICENSE | 7 - .../hapi/node_modules/multiparty/README.md | 163 - .../multiparty/examples/azureblobstorage.js | 41 - .../node_modules/multiparty/examples/s3.js | 74 - .../multiparty/examples/upload.js | 37 - .../hapi/node_modules/multiparty/index.js | 596 --- .../node_modules/readable-stream/.npmignore | 5 - .../node_modules/readable-stream/LICENSE | 18 - .../node_modules/readable-stream/README.md | 15 - .../node_modules/readable-stream/duplex.js | 1 - .../node_modules/core-util-is/README.md | 3 - .../node_modules/core-util-is/float.patch | 604 ---- .../node_modules/core-util-is/package.json | 36 - .../node_modules/core-util-is/util.js | 106 - .../node_modules/inherits/LICENSE | 16 - .../node_modules/inherits/README.md | 42 - .../node_modules/inherits/inherits.js | 1 - .../node_modules/inherits/inherits_browser.js | 23 - .../node_modules/inherits/package.json | 33 - .../node_modules/inherits/test.js | 25 - .../node_modules/isarray/README.md | 54 - .../node_modules/isarray/component.json | 19 - .../node_modules/isarray/index.js | 3 - .../node_modules/isarray/package.json | 54 - .../node_modules/string_decoder/.npmignore | 2 - .../node_modules/string_decoder/LICENSE | 20 - .../node_modules/string_decoder/README.md | 7 - .../node_modules/string_decoder/index.js | 221 -- .../node_modules/string_decoder/package.json | 32 - .../node_modules/readable-stream/package.json | 70 - .../readable-stream/passthrough.js | 1 - .../node_modules/readable-stream/readable.js | 8 - .../node_modules/readable-stream/transform.js | 1 - .../node_modules/readable-stream/writable.js | 1 - .../node_modules/stream-counter/.npmignore | 1 - .../node_modules/stream-counter/README.md | 14 - .../node_modules/stream-counter/index.js | 16 - .../node_modules/stream-counter/package.json | 49 - .../node_modules/stream-counter/test/test.js | 20 - .../node_modules/stream-counter/test/test.txt | 1 - .../hapi/node_modules/multiparty/package.json | 58 - .../multiparty/test/bench-multipart-parser.js | 76 - .../test/fixture/file/beta-sticker-1.png | Bin 1660 -> 0 bytes .../test/fixture/file/binaryfile.tar.gz | Bin 301 -> 0 bytes .../multiparty/test/fixture/file/blank.gif | Bin 49 -> 0 bytes .../test/fixture/file/funkyfilename.txt | 1 - .../test/fixture/file/menu_separator.png | Bin 931 -> 0 bytes .../multiparty/test/fixture/file/pf1y5.png | Bin 768323 -> 0 bytes .../multiparty/test/fixture/file/plain.txt | 1 - .../http/encoding/beta-sticker-1.png.http | 12 - .../http/encoding/binaryfile.tar.gz.http | 12 - .../test/fixture/http/encoding/blank.gif.http | 12 - .../http/encoding/menu_seperator.png.http | 12 - .../test/fixture/http/encoding/pf1y5.png.http | Bin 769076 -> 0 bytes .../test/fixture/http/encoding/plain.txt.http | 13 - .../http/no-filename/filename-name.http | 13 - .../fixture/http/no-filename/generic.http | 13 - .../test/fixture/http/preamble/crlf.http | 13 - .../test/fixture/http/preamble/preamble.http | 13 - .../http/special-chars-in-filename/info.md | 3 - .../osx-chrome-13.http | 26 - .../osx-firefox-3.6.http | 24 - .../osx-safari-5.http | 23 - .../xp-chrome-12.http | 24 - .../special-chars-in-filename/xp-ie-7.http | 22 - .../special-chars-in-filename/xp-ie-8.http | 22 - .../xp-safari-5.http | 22 - .../http/workarounds/missing-hyphens1.http | 12 - .../http/workarounds/missing-hyphens2.http | 12 - .../multiparty/test/fixture/js/encoding.js | 69 - .../multiparty/test/fixture/js/no-filename.js | 9 - .../multiparty/test/fixture/js/preamble.js | 9 - .../fixture/js/special-chars-in-filename.js | 30 - .../multiparty/test/fixture/js/workarounds.js | 8 - .../test/fixture/multi_video.upload | Bin 1953749 -> 0 bytes .../multiparty/test/fixture/multipart.js | 72 - .../node_modules/multiparty/test/record.js | 47 - .../standalone/test-connection-aborted.js | 27 - .../test-content-transfer-encoding.js | 52 - .../test/standalone/test-invalid.js | 35 - .../test/standalone/test-issue-15.js | 88 - .../test/standalone/test-issue-4.js | 51 - .../test/standalone/test-issue-46.js | 49 - .../hapi/node_modules/multiparty/test/test.js | 117 - .../hapi/node_modules/negotiator/LICENSE | 27 - .../negotiator/examples/accept.js | 47 - .../negotiator/examples/charset.js | 52 - .../negotiator/examples/encoding.js | 48 - .../negotiator/examples/language.js | 44 - .../hapi/node_modules/negotiator/package.json | 57 - .../hapi/node_modules/negotiator/readme.md | 132 - .../node_modules/negotiator/test/charset.js | 62 - .../node_modules/negotiator/test/encoding.js | 70 - .../node_modules/negotiator/test/language.js | 70 - .../node_modules/negotiator/test/mediaType.js | 70 - .../hapi/node_modules/optimist/.travis.yml | 4 - .../hapi/node_modules/optimist/LICENSE | 21 - .../node_modules/optimist/example/bool.js | 10 - .../optimist/example/boolean_double.js | 7 - .../optimist/example/boolean_single.js | 7 - .../optimist/example/default_hash.js | 8 - .../optimist/example/default_singles.js | 7 - .../node_modules/optimist/example/divide.js | 8 - .../optimist/example/line_count.js | 20 - .../optimist/example/line_count_options.js | 29 - .../optimist/example/line_count_wrap.js | 29 - .../node_modules/optimist/example/nonopt.js | 4 - .../node_modules/optimist/example/reflect.js | 2 - .../node_modules/optimist/example/short.js | 3 - .../node_modules/optimist/example/string.js | 11 - .../optimist/example/usage-options.js | 19 - .../hapi/node_modules/optimist/example/xup.js | 10 - .../hapi/node_modules/optimist/index.js | 343 -- .../node_modules/minimist/.travis.yml | 4 - .../optimist/node_modules/minimist/LICENSE | 18 - .../node_modules/minimist/example/parse.js | 2 - .../optimist/node_modules/minimist/index.js | 187 - .../node_modules/minimist/package.json | 50 - .../node_modules/minimist/readme.markdown | 73 - .../node_modules/minimist/test/bool.js | 119 - .../node_modules/minimist/test/dash.js | 24 - .../minimist/test/default_bool.js | 20 - .../node_modules/minimist/test/dotted.js | 22 - .../node_modules/minimist/test/long.js | 31 - .../node_modules/minimist/test/num.js | 36 - .../node_modules/minimist/test/parse.js | 197 - .../minimist/test/parse_modified.js | 9 - .../node_modules/minimist/test/short.js | 67 - .../node_modules/minimist/test/whitespace.js | 8 - .../optimist/node_modules/wordwrap/LICENSE | 18 - .../node_modules/wordwrap/README.markdown | 70 - .../node_modules/wordwrap/example/center.js | 10 - .../node_modules/wordwrap/example/meat.js | 3 - .../optimist/node_modules/wordwrap/index.js | 76 - .../node_modules/wordwrap/package.json | 63 - .../node_modules/wordwrap/test/break.js | 30 - .../node_modules/wordwrap/test/idleness.txt | 63 - .../node_modules/wordwrap/test/wrap.js | 31 - .../hapi/node_modules/optimist/package.json | 47 - .../node_modules/optimist/readme.markdown | 513 --- .../hapi/node_modules/optimist/test/_.js | 71 - .../hapi/node_modules/optimist/test/_/argv.js | 2 - .../hapi/node_modules/optimist/test/_/bin.js | 3 - .../hapi/node_modules/optimist/test/dash.js | 31 - .../hapi/node_modules/optimist/test/parse.js | 446 --- .../optimist/test/parse_modified.js | 14 - .../hapi/node_modules/optimist/test/short.js | 16 - .../hapi/node_modules/optimist/test/usage.js | 292 -- .../node_modules/optimist/test/whitespace.js | 8 - .../hapi/node_modules/semver/.npmignore | 1 - node_modules/hapi/node_modules/semver/LICENSE | 27 - .../hapi/node_modules/semver/Makefile | 24 - .../hapi/node_modules/semver/README.md | 111 - .../hapi/node_modules/semver/bin/semver | 119 - node_modules/hapi/node_modules/semver/foot.js | 6 - node_modules/hapi/node_modules/semver/head.js | 2 - .../hapi/node_modules/semver/package.json | 32 - node_modules/hapi/node_modules/semver/r.js | 4 - .../node_modules/semver/semver.browser.js | 851 ----- .../node_modules/semver/semver.browser.js.gz | Bin 6077 -> 0 bytes .../hapi/node_modules/semver/semver.js | 855 ----- .../hapi/node_modules/semver/semver.min.js | 1 - .../hapi/node_modules/semver/semver.min.js.gz | Bin 2850 -> 0 bytes .../hapi/node_modules/semver/test/amd.js | 15 - .../hapi/node_modules/semver/test/index.js | 533 --- .../node_modules/semver/test/no-module.js | 19 - .../hapi/node_modules/shot/.travis.yml | 3 +- node_modules/hapi/node_modules/shot/LICENSE | 15 +- node_modules/hapi/node_modules/shot/Makefile | 11 - node_modules/hapi/node_modules/shot/README.md | 9 +- .../hapi/node_modules/shot/examples/http.js | 1 - node_modules/hapi/node_modules/shot/index.js | 2 +- .../hapi/node_modules/shot/package.json | 56 +- .../hapi/node_modules/shot/test/index.js | 670 ++-- node_modules/hapi/package.json | 121 +- .../hapi/proposals/RFC.CacheMemorySize.md | 28 - .../hapi/proposals/RFC.DocGeneration.md | 74 - .../hapi/proposals/RFC.QueryConfig.md | 447 --- .../hapi/proposals/RFC.QueryValidation.md | 188 - node_modules/hapi/proposals/RFC.Throttling.md | 122 - .../hapi/proposals/Routing/RFC.RouteConfig.md | 266 -- .../hapi/proposals/Routing/new_routes.js | 133 - node_modules/hapi/proposals/Routing/routes.js | 83 - node_modules/hapi/test/integration/.hidden | 1 - node_modules/hapi/test/integration/auth.js | 1549 -------- node_modules/hapi/test/integration/cache.js | 161 - .../hapi/test/integration/clientTimeout.js | 185 - .../hapi/test/integration/composer.js | 124 - .../test/integration/directory/index.html | 1 - .../invalid/index.html/do-not-delete | 0 .../directory/subdir/subsubdir/placeholder | 0 .../integration/directory/subdir/test.txt | 0 node_modules/hapi/test/integration/ext.js | 95 - .../hapi/test/integration/file/note.txt | 1 - node_modules/hapi/test/integration/gzip.js | 218 -- node_modules/hapi/test/integration/hapi.js | 271 -- .../hapi/test/integration/notFound.js | 90 - node_modules/hapi/test/integration/pack.js | 617 ---- .../test/integration/pack/--auth/index.js | 27 - .../test/integration/pack/--auth/package.json | 7 - .../test/integration/pack/--deps1/index.js | 20 - .../integration/pack/--deps1/package.json | 7 - .../test/integration/pack/--deps2/index.js | 18 - .../integration/pack/--deps2/package.json | 7 - .../test/integration/pack/--deps3/index.js | 18 - .../integration/pack/--deps3/package.json | 7 - .../integration/pack/--loaded/package.json | 7 - .../test/integration/pack/--skip/package.json | 7 - .../integration/pack/--test1/package.json | 7 - .../integration/pack/--test2/package.json | 7 - .../integration/pack/--views/package.json | 7 - .../pack/--views/templates/test.html | 1 - node_modules/hapi/test/integration/payload.js | 649 ---- .../hapi/test/integration/prerequisites.js | 272 -- node_modules/hapi/test/integration/proxy.js | 643 ---- node_modules/hapi/test/integration/request.js | 463 --- .../hapi/test/integration/response.js | 2022 ----------- node_modules/hapi/test/integration/route.js | 175 - node_modules/hapi/test/integration/router.js | 142 - .../hapi/test/integration/security.js | 269 -- node_modules/hapi/test/integration/server.js | 176 - .../hapi/test/integration/serverTimeout.js | 358 -- node_modules/hapi/test/unit/auth.js | 497 --- node_modules/hapi/test/unit/client.js | 201 -- node_modules/hapi/test/unit/ext.js | 137 - node_modules/hapi/test/unit/payload.js | 190 - node_modules/hapi/test/unit/request.js | 225 -- .../hapi/test/unit/response/directory.js | 39 - node_modules/hapi/test/unit/response/view.js | 42 - node_modules/hapi/test/unit/route.js | 359 -- node_modules/hapi/test/unit/schema.js | 142 - node_modules/hapi/test/unit/server.js | 606 ---- node_modules/hapi/test/unit/state.js | 397 -- .../unit/templates/invalid/badmustache.html | 2 - .../test/unit/templates/invalid/test.html | 3 - .../hapi/test/unit/templates/layout.html | 9 - .../test/unit/templates/valid/handler.html | 11 - .../unit/templates/valid/helpers/uppercase.js | 4 - .../hapi/test/unit/templates/valid/index.jade | 4 - .../test/unit/templates/valid/layout.jade | 4 - .../unit/templates/valid/partials/nav.html | 1 - .../templates/valid/partials/nested/nav.html | 1 - .../hapi/test/unit/templates/valid/test.html | 3 - .../hapi/test/unit/templates/valid/test.jade | 1 - .../unit/templates/valid/testHelpers.html | 1 - .../test/unit/templates/valid/testMulti.jade | 4 - .../unit/templates/valid/testPartials.html | 1 - node_modules/hapi/test/unit/utils.js | 32 - node_modules/hapi/test/unit/validation.js | 290 -- node_modules/hapi/test/unit/views.js | 277 -- node_modules/lout/.npmignore | 18 - node_modules/lout/.travis.yml | 5 - node_modules/lout/AUTHORS | 3 - node_modules/lout/LICENSE | 24 - node_modules/lout/Makefile | 8 - node_modules/lout/README.md | 18 - node_modules/lout/images/lout.png | Bin 41674 -> 0 bytes node_modules/lout/index.js | 1 - node_modules/lout/package.json | 79 - node_modules/lout/templates/index.html | 36 - node_modules/lout/templates/route.html | 163 - node_modules/lout/test/index.js | 111 - package.json | 6 +- server.js | 20 +- templates/index.html | 3 + 541 files changed, 9503 insertions(+), 57363 deletions(-) rename routes.js => backend.js (69%) create mode 100755 bluetooth.js create mode 100755 frontend.js delete mode 100755 images/banjo.png delete mode 100755 images/headers.png delete mode 100755 images/products.png delete mode 120000 node_modules/.bin/hapi delete mode 100644 node_modules/handlebars/.jshintrc delete mode 100644 node_modules/handlebars/.rspec delete mode 100644 node_modules/handlebars/bower.json delete mode 100644 node_modules/handlebars/global-test.js delete mode 100644 node_modules/handlebars/global.js delete mode 100644 node_modules/handlebars/handlebars-source.gemspec delete mode 100644 node_modules/handlebars/handlebars.js.nuspec delete mode 100755 node_modules/handlebars/min.sh delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/.npmignore delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/.travis.yml delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/CHANGELOG.md delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/LICENSE delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/Makefile.dryice.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/README.md delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/LICENSE delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/README.md delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/amdefine.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/intercept.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/package.json delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/package.json delete mode 100755 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/run-tests.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-api.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-array-set.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64-vlq.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-binary-search.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-dog-fooding.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-consumer.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-generator.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-node.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-util.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/util.js delete mode 100644 node_modules/handlebars/test.js delete mode 100644 node_modules/hapi/.gitattributes delete mode 100755 node_modules/hapi/Makefile delete mode 100755 node_modules/hapi/bin/hapi delete mode 100644 node_modules/hapi/docs/Plugins.md delete mode 100755 node_modules/hapi/docs/Reference.md delete mode 100755 node_modules/hapi/docs/Style.md delete mode 100755 node_modules/hapi/examples/auth.js delete mode 100755 node_modules/hapi/examples/cache.js delete mode 100755 node_modules/hapi/examples/composer.json delete mode 100755 node_modules/hapi/examples/cookie.js delete mode 100755 node_modules/hapi/examples/directory/index.html delete mode 100755 node_modules/hapi/examples/directory/server.js delete mode 100755 node_modules/hapi/examples/errors.js delete mode 100755 node_modules/hapi/examples/extensions.js delete mode 100644 node_modules/hapi/examples/favicon.ico delete mode 100755 node_modules/hapi/examples/favicon.js delete mode 100755 node_modules/hapi/examples/file/index.html delete mode 100755 node_modules/hapi/examples/file/server.js delete mode 100755 node_modules/hapi/examples/files.js delete mode 100755 node_modules/hapi/examples/helpers.js delete mode 100755 node_modules/hapi/examples/injection.js delete mode 100755 node_modules/hapi/examples/jsonp.js delete mode 100755 node_modules/hapi/examples/prerequisites.js delete mode 100755 node_modules/hapi/examples/proxy.js delete mode 100755 node_modules/hapi/examples/socketio.js delete mode 100755 node_modules/hapi/examples/stream.js delete mode 100755 node_modules/hapi/examples/tails.js delete mode 100755 node_modules/hapi/examples/validation.js delete mode 100755 node_modules/hapi/examples/views/cms/_pages/.placeholder delete mode 100644 node_modules/hapi/examples/views/cms/_pages/Test delete mode 100755 node_modules/hapi/examples/views/cms/pages.js delete mode 100755 node_modules/hapi/examples/views/cms/server.js delete mode 100755 node_modules/hapi/examples/views/cms/views/create.html delete mode 100755 node_modules/hapi/examples/views/cms/views/edit.html delete mode 100755 node_modules/hapi/examples/views/cms/views/index.html delete mode 100755 node_modules/hapi/examples/views/cms/views/layout.html delete mode 100755 node_modules/hapi/examples/views/cms/views/page.html delete mode 100755 node_modules/hapi/examples/views/cms/views/partials/footer.html delete mode 100755 node_modules/hapi/examples/views/cms/views/partials/nav.html delete mode 100755 node_modules/hapi/examples/views/handlebars/basic.js delete mode 100755 node_modules/hapi/examples/views/handlebars/layout.js delete mode 100755 node_modules/hapi/examples/views/handlebars/partials.js delete mode 100755 node_modules/hapi/examples/views/handlebars/templates/basic/index.html delete mode 100755 node_modules/hapi/examples/views/handlebars/templates/layout.html delete mode 100755 node_modules/hapi/examples/views/handlebars/templates/withLayout/index.html delete mode 100755 node_modules/hapi/examples/views/handlebars/templates/withPartials/footer.html delete mode 100755 node_modules/hapi/examples/views/handlebars/templates/withPartials/header.html delete mode 100755 node_modules/hapi/examples/views/handlebars/templates/withPartials/index.html delete mode 100755 node_modules/hapi/examples/views/jade/index.js delete mode 100755 node_modules/hapi/examples/views/jade/templates/about.jade delete mode 100755 node_modules/hapi/examples/views/jade/templates/includes/foot.jade delete mode 100755 node_modules/hapi/examples/views/jade/templates/includes/head.jade delete mode 100755 node_modules/hapi/examples/views/jade/templates/index.jade delete mode 100755 node_modules/hapi/examples/views/jade/templates/layout.jade delete mode 100755 node_modules/hapi/examples/views/mixed/index.js delete mode 100755 node_modules/hapi/examples/views/mixed/templates/handlebars.html delete mode 100755 node_modules/hapi/examples/views/mixed/templates/index.jade delete mode 100755 node_modules/hapi/index.js delete mode 100644 node_modules/hapi/lab_runner.js delete mode 120000 node_modules/hapi/node_modules/.bin/semver delete mode 100644 node_modules/hapi/node_modules/async/LICENSE delete mode 100644 node_modules/hapi/node_modules/async/README.md delete mode 100644 node_modules/hapi/node_modules/async/component.json delete mode 100644 node_modules/hapi/node_modules/async/package.json delete mode 100755 node_modules/hapi/node_modules/boom/Makefile delete mode 100644 node_modules/hapi/node_modules/catbox/examples/mongo.js delete mode 100644 node_modules/hapi/node_modules/catbox/examples/redis.js delete mode 100755 node_modules/hapi/node_modules/catbox/test/common.js delete mode 100755 node_modules/hapi/node_modules/catbox/test/defaults.js delete mode 100755 node_modules/hapi/node_modules/catbox/test/helper.js delete mode 100755 node_modules/hapi/node_modules/catbox/test/memory.js delete mode 100755 node_modules/hapi/node_modules/catbox/test/mongo.js delete mode 100755 node_modules/hapi/node_modules/catbox/test/redis.js delete mode 100644 node_modules/hapi/node_modules/hawk/.npmignore delete mode 100755 node_modules/hapi/node_modules/hawk/.travis.yml delete mode 100755 node_modules/hapi/node_modules/hawk/LICENSE delete mode 100755 node_modules/hapi/node_modules/hawk/Makefile delete mode 100755 node_modules/hapi/node_modules/hawk/README.md delete mode 100644 node_modules/hapi/node_modules/hawk/component.json delete mode 100755 node_modules/hapi/node_modules/hawk/example/usage.js delete mode 100755 node_modules/hapi/node_modules/hawk/images/hawk.png delete mode 100755 node_modules/hapi/node_modules/hawk/images/logo.png delete mode 100755 node_modules/hapi/node_modules/hawk/index.js delete mode 100644 node_modules/hapi/node_modules/hawk/node_modules/boom/.npmignore delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/boom/.travis.yml delete mode 100644 node_modules/hapi/node_modules/hawk/node_modules/boom/AUTHORS delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/boom/LICENSE delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/boom/Makefile delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/boom/README.md delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/boom/images/boom.png delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/boom/index.js delete mode 100644 node_modules/hapi/node_modules/hawk/node_modules/boom/package.json delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/boom/test/index.js delete mode 100644 node_modules/hapi/node_modules/hawk/node_modules/cryptiles/.npmignore delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/cryptiles/.travis.yml delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/cryptiles/LICENSE delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/cryptiles/Makefile delete mode 100644 node_modules/hapi/node_modules/hawk/node_modules/cryptiles/README.md delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/cryptiles/index.js delete mode 100644 node_modules/hapi/node_modules/hawk/node_modules/cryptiles/package.json delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/cryptiles/test/index.js delete mode 100644 node_modules/hapi/node_modules/hawk/node_modules/hoek/.npmignore delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/hoek/.travis.yml delete mode 100644 node_modules/hapi/node_modules/hawk/node_modules/hoek/AUTHORS delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/hoek/LICENSE delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/hoek/Makefile delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/hoek/README.md delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/hoek/images/hoek.png delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/hoek/index.js delete mode 100644 node_modules/hapi/node_modules/hawk/node_modules/hoek/package.json delete mode 100644 node_modules/hapi/node_modules/hawk/node_modules/hoek/test/escaper.js delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/hoek/test/index.js delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/hoek/test/modules/test1.js delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/hoek/test/modules/test2.js delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/hoek/test/modules/test3.js delete mode 100644 node_modules/hapi/node_modules/hawk/node_modules/sntp/.npmignore delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/sntp/.travis.yml delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/sntp/LICENSE delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/sntp/Makefile delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/sntp/README.md delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/sntp/examples/offset.js delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/sntp/examples/time.js delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/sntp/index.js delete mode 100644 node_modules/hapi/node_modules/hawk/node_modules/sntp/node_modules/hoek/.npmignore delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/sntp/node_modules/hoek/.travis.yml delete mode 100644 node_modules/hapi/node_modules/hawk/node_modules/sntp/node_modules/hoek/CONTRIBUTING.md delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/sntp/node_modules/hoek/LICENSE delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/sntp/node_modules/hoek/Makefile delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/sntp/node_modules/hoek/README.md delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/sntp/node_modules/hoek/images/hoek.png delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/sntp/node_modules/hoek/index.js delete mode 100644 node_modules/hapi/node_modules/hawk/node_modules/sntp/node_modules/hoek/package.json delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/escaper.js delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/index.js delete mode 100644 node_modules/hapi/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/modules/ignore.txt delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/modules/test1.js delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/modules/test2.js delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/modules/test3.js delete mode 100644 node_modules/hapi/node_modules/hawk/node_modules/sntp/package.json delete mode 100755 node_modules/hapi/node_modules/hawk/node_modules/sntp/test/index.js delete mode 100644 node_modules/hapi/node_modules/hawk/package.json delete mode 100755 node_modules/hapi/node_modules/hawk/test/browser.js delete mode 100755 node_modules/hapi/node_modules/hawk/test/client.js delete mode 100755 node_modules/hapi/node_modules/hawk/test/crypto.js delete mode 100755 node_modules/hapi/node_modules/hawk/test/index.js delete mode 100755 node_modules/hapi/node_modules/hawk/test/message.js delete mode 100755 node_modules/hapi/node_modules/hawk/test/readme.js delete mode 100755 node_modules/hapi/node_modules/hawk/test/server.js delete mode 100755 node_modules/hapi/node_modules/hawk/test/uri.js delete mode 100755 node_modules/hapi/node_modules/hawk/test/utils.js mode change 100644 => 100755 node_modules/hapi/node_modules/hoek/test/escaper.js delete mode 100755 node_modules/hapi/node_modules/joi/Makefile mode change 100755 => 100644 node_modules/hapi/node_modules/joi/README.md delete mode 100644 node_modules/hapi/node_modules/joi/languages/en-US.json delete mode 100644 node_modules/hapi/node_modules/joi/test/messages.js delete mode 100755 node_modules/hapi/node_modules/joi/test/set.js delete mode 100755 node_modules/hapi/node_modules/joi/test/support/meta.js delete mode 100644 node_modules/hapi/node_modules/joi/test/types/any.js delete mode 100755 node_modules/hapi/node_modules/joi/test/types/array.js delete mode 100755 node_modules/hapi/node_modules/joi/test/types/base.js delete mode 100755 node_modules/hapi/node_modules/joi/test/types/boolean.js delete mode 100755 node_modules/hapi/node_modules/joi/test/types/function.js delete mode 100755 node_modules/hapi/node_modules/joi/test/types/index.js delete mode 100755 node_modules/hapi/node_modules/joi/test/types/number.js delete mode 100755 node_modules/hapi/node_modules/joi/test/types/object.js delete mode 100755 node_modules/hapi/node_modules/joi/test/types/string.js delete mode 100644 node_modules/hapi/node_modules/lru-cache/.npmignore delete mode 100644 node_modules/hapi/node_modules/lru-cache/AUTHORS delete mode 100644 node_modules/hapi/node_modules/lru-cache/LICENSE delete mode 100644 node_modules/hapi/node_modules/lru-cache/README.md delete mode 100644 node_modules/hapi/node_modules/lru-cache/bench.js delete mode 100644 node_modules/hapi/node_modules/lru-cache/package.json delete mode 100644 node_modules/hapi/node_modules/lru-cache/test/basic.js delete mode 100644 node_modules/hapi/node_modules/lru-cache/test/foreach.js delete mode 100644 node_modules/hapi/node_modules/lru-cache/test/memory-leak.js delete mode 100644 node_modules/hapi/node_modules/mime/LICENSE delete mode 100644 node_modules/hapi/node_modules/mime/README.md delete mode 100644 node_modules/hapi/node_modules/mime/mime.js delete mode 100644 node_modules/hapi/node_modules/mime/package.json delete mode 100644 node_modules/hapi/node_modules/mime/test.js delete mode 100644 node_modules/hapi/node_modules/mime/types/mime.types delete mode 100644 node_modules/hapi/node_modules/mime/types/node.types delete mode 100644 node_modules/hapi/node_modules/multiparty/.jshintrc delete mode 100644 node_modules/hapi/node_modules/multiparty/.npmignore delete mode 100644 node_modules/hapi/node_modules/multiparty/.travis.yml delete mode 100644 node_modules/hapi/node_modules/multiparty/CHANGELOG.md delete mode 100644 node_modules/hapi/node_modules/multiparty/LICENSE delete mode 100644 node_modules/hapi/node_modules/multiparty/README.md delete mode 100644 node_modules/hapi/node_modules/multiparty/examples/azureblobstorage.js delete mode 100644 node_modules/hapi/node_modules/multiparty/examples/s3.js delete mode 100644 node_modules/hapi/node_modules/multiparty/examples/upload.js delete mode 100755 node_modules/hapi/node_modules/multiparty/index.js delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/.npmignore delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/LICENSE delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/README.md delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/duplex.js delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/node_modules/core-util-is/README.md delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/node_modules/core-util-is/float.patch delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/node_modules/core-util-is/package.json delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/node_modules/core-util-is/util.js delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/node_modules/inherits/LICENSE delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/node_modules/inherits/README.md delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/node_modules/inherits/inherits.js delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/node_modules/inherits/inherits_browser.js delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/node_modules/inherits/package.json delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/node_modules/inherits/test.js delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/node_modules/isarray/README.md delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/node_modules/isarray/component.json delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/node_modules/isarray/index.js delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/node_modules/isarray/package.json delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/node_modules/string_decoder/.npmignore delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/node_modules/string_decoder/LICENSE delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/node_modules/string_decoder/README.md delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/node_modules/string_decoder/index.js delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/node_modules/string_decoder/package.json delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/package.json delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/passthrough.js delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/readable.js delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/transform.js delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/readable-stream/writable.js delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/stream-counter/.npmignore delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/stream-counter/README.md delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/stream-counter/index.js delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/stream-counter/package.json delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/stream-counter/test/test.js delete mode 100644 node_modules/hapi/node_modules/multiparty/node_modules/stream-counter/test/test.txt delete mode 100644 node_modules/hapi/node_modules/multiparty/package.json delete mode 100644 node_modules/hapi/node_modules/multiparty/test/bench-multipart-parser.js delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/file/beta-sticker-1.png delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/file/binaryfile.tar.gz delete mode 100755 node_modules/hapi/node_modules/multiparty/test/fixture/file/blank.gif delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/file/funkyfilename.txt delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/file/menu_separator.png delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/file/pf1y5.png delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/file/plain.txt delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/http/encoding/beta-sticker-1.png.http delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/http/encoding/binaryfile.tar.gz.http delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/http/encoding/blank.gif.http delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/http/encoding/menu_seperator.png.http delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/http/encoding/pf1y5.png.http delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/http/encoding/plain.txt.http delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/http/no-filename/filename-name.http delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/http/no-filename/generic.http delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/http/preamble/crlf.http delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/http/preamble/preamble.http delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/http/special-chars-in-filename/info.md delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/http/special-chars-in-filename/osx-chrome-13.http delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/http/special-chars-in-filename/osx-firefox-3.6.http delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/http/special-chars-in-filename/osx-safari-5.http delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/http/special-chars-in-filename/xp-chrome-12.http delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/http/special-chars-in-filename/xp-ie-7.http delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/http/special-chars-in-filename/xp-ie-8.http delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/http/special-chars-in-filename/xp-safari-5.http delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/http/workarounds/missing-hyphens1.http delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/http/workarounds/missing-hyphens2.http delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/js/encoding.js delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/js/no-filename.js delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/js/preamble.js delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/js/special-chars-in-filename.js delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/js/workarounds.js delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/multi_video.upload delete mode 100644 node_modules/hapi/node_modules/multiparty/test/fixture/multipart.js delete mode 100644 node_modules/hapi/node_modules/multiparty/test/record.js delete mode 100644 node_modules/hapi/node_modules/multiparty/test/standalone/test-connection-aborted.js delete mode 100644 node_modules/hapi/node_modules/multiparty/test/standalone/test-content-transfer-encoding.js delete mode 100644 node_modules/hapi/node_modules/multiparty/test/standalone/test-invalid.js delete mode 100644 node_modules/hapi/node_modules/multiparty/test/standalone/test-issue-15.js delete mode 100644 node_modules/hapi/node_modules/multiparty/test/standalone/test-issue-4.js delete mode 100644 node_modules/hapi/node_modules/multiparty/test/standalone/test-issue-46.js delete mode 100644 node_modules/hapi/node_modules/multiparty/test/test.js delete mode 100644 node_modules/hapi/node_modules/negotiator/LICENSE delete mode 100644 node_modules/hapi/node_modules/negotiator/examples/accept.js delete mode 100644 node_modules/hapi/node_modules/negotiator/examples/charset.js delete mode 100644 node_modules/hapi/node_modules/negotiator/examples/encoding.js delete mode 100644 node_modules/hapi/node_modules/negotiator/examples/language.js delete mode 100644 node_modules/hapi/node_modules/negotiator/package.json delete mode 100644 node_modules/hapi/node_modules/negotiator/readme.md delete mode 100644 node_modules/hapi/node_modules/negotiator/test/charset.js delete mode 100644 node_modules/hapi/node_modules/negotiator/test/encoding.js delete mode 100644 node_modules/hapi/node_modules/negotiator/test/language.js delete mode 100644 node_modules/hapi/node_modules/negotiator/test/mediaType.js delete mode 100644 node_modules/hapi/node_modules/optimist/.travis.yml delete mode 100644 node_modules/hapi/node_modules/optimist/LICENSE delete mode 100644 node_modules/hapi/node_modules/optimist/example/bool.js delete mode 100644 node_modules/hapi/node_modules/optimist/example/boolean_double.js delete mode 100644 node_modules/hapi/node_modules/optimist/example/boolean_single.js delete mode 100644 node_modules/hapi/node_modules/optimist/example/default_hash.js delete mode 100644 node_modules/hapi/node_modules/optimist/example/default_singles.js delete mode 100644 node_modules/hapi/node_modules/optimist/example/divide.js delete mode 100644 node_modules/hapi/node_modules/optimist/example/line_count.js delete mode 100644 node_modules/hapi/node_modules/optimist/example/line_count_options.js delete mode 100644 node_modules/hapi/node_modules/optimist/example/line_count_wrap.js delete mode 100644 node_modules/hapi/node_modules/optimist/example/nonopt.js delete mode 100644 node_modules/hapi/node_modules/optimist/example/reflect.js delete mode 100644 node_modules/hapi/node_modules/optimist/example/short.js delete mode 100644 node_modules/hapi/node_modules/optimist/example/string.js delete mode 100644 node_modules/hapi/node_modules/optimist/example/usage-options.js delete mode 100644 node_modules/hapi/node_modules/optimist/example/xup.js delete mode 100644 node_modules/hapi/node_modules/optimist/index.js delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/minimist/.travis.yml delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/minimist/LICENSE delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/minimist/example/parse.js delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/minimist/index.js delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/minimist/package.json delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/minimist/readme.markdown delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/minimist/test/bool.js delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/minimist/test/dash.js delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/minimist/test/default_bool.js delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/minimist/test/dotted.js delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/minimist/test/long.js delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/minimist/test/num.js delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/minimist/test/parse.js delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/minimist/test/parse_modified.js delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/minimist/test/short.js delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/minimist/test/whitespace.js delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/wordwrap/LICENSE delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/wordwrap/README.markdown delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/wordwrap/example/center.js delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/wordwrap/example/meat.js delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/wordwrap/index.js delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/wordwrap/package.json delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/wordwrap/test/break.js delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/wordwrap/test/idleness.txt delete mode 100644 node_modules/hapi/node_modules/optimist/node_modules/wordwrap/test/wrap.js delete mode 100644 node_modules/hapi/node_modules/optimist/package.json delete mode 100644 node_modules/hapi/node_modules/optimist/readme.markdown delete mode 100644 node_modules/hapi/node_modules/optimist/test/_.js delete mode 100644 node_modules/hapi/node_modules/optimist/test/_/argv.js delete mode 100755 node_modules/hapi/node_modules/optimist/test/_/bin.js delete mode 100644 node_modules/hapi/node_modules/optimist/test/dash.js delete mode 100644 node_modules/hapi/node_modules/optimist/test/parse.js delete mode 100644 node_modules/hapi/node_modules/optimist/test/parse_modified.js delete mode 100644 node_modules/hapi/node_modules/optimist/test/short.js delete mode 100644 node_modules/hapi/node_modules/optimist/test/usage.js delete mode 100644 node_modules/hapi/node_modules/optimist/test/whitespace.js delete mode 100644 node_modules/hapi/node_modules/semver/.npmignore delete mode 100644 node_modules/hapi/node_modules/semver/LICENSE delete mode 100644 node_modules/hapi/node_modules/semver/Makefile delete mode 100644 node_modules/hapi/node_modules/semver/README.md delete mode 100755 node_modules/hapi/node_modules/semver/bin/semver delete mode 100644 node_modules/hapi/node_modules/semver/foot.js delete mode 100644 node_modules/hapi/node_modules/semver/head.js delete mode 100644 node_modules/hapi/node_modules/semver/package.json delete mode 100644 node_modules/hapi/node_modules/semver/r.js delete mode 100644 node_modules/hapi/node_modules/semver/semver.browser.js delete mode 100644 node_modules/hapi/node_modules/semver/semver.browser.js.gz delete mode 100644 node_modules/hapi/node_modules/semver/semver.js delete mode 100644 node_modules/hapi/node_modules/semver/semver.min.js delete mode 100644 node_modules/hapi/node_modules/semver/semver.min.js.gz delete mode 100644 node_modules/hapi/node_modules/semver/test/amd.js delete mode 100644 node_modules/hapi/node_modules/semver/test/index.js delete mode 100644 node_modules/hapi/node_modules/semver/test/no-module.js delete mode 100755 node_modules/hapi/node_modules/shot/Makefile delete mode 100755 node_modules/hapi/proposals/RFC.CacheMemorySize.md delete mode 100755 node_modules/hapi/proposals/RFC.DocGeneration.md delete mode 100755 node_modules/hapi/proposals/RFC.QueryConfig.md delete mode 100755 node_modules/hapi/proposals/RFC.QueryValidation.md delete mode 100755 node_modules/hapi/proposals/RFC.Throttling.md delete mode 100755 node_modules/hapi/proposals/Routing/RFC.RouteConfig.md delete mode 100755 node_modules/hapi/proposals/Routing/new_routes.js delete mode 100755 node_modules/hapi/proposals/Routing/routes.js delete mode 100755 node_modules/hapi/test/integration/.hidden delete mode 100755 node_modules/hapi/test/integration/auth.js delete mode 100755 node_modules/hapi/test/integration/cache.js delete mode 100755 node_modules/hapi/test/integration/clientTimeout.js delete mode 100755 node_modules/hapi/test/integration/composer.js delete mode 100755 node_modules/hapi/test/integration/directory/index.html delete mode 100755 node_modules/hapi/test/integration/directory/invalid/index.html/do-not-delete delete mode 100755 node_modules/hapi/test/integration/directory/subdir/subsubdir/placeholder delete mode 100755 node_modules/hapi/test/integration/directory/subdir/test.txt delete mode 100755 node_modules/hapi/test/integration/ext.js delete mode 100644 node_modules/hapi/test/integration/file/note.txt delete mode 100755 node_modules/hapi/test/integration/gzip.js delete mode 100644 node_modules/hapi/test/integration/hapi.js delete mode 100755 node_modules/hapi/test/integration/notFound.js delete mode 100755 node_modules/hapi/test/integration/pack.js delete mode 100755 node_modules/hapi/test/integration/pack/--auth/index.js delete mode 100755 node_modules/hapi/test/integration/pack/--auth/package.json delete mode 100755 node_modules/hapi/test/integration/pack/--deps1/index.js delete mode 100755 node_modules/hapi/test/integration/pack/--deps1/package.json delete mode 100755 node_modules/hapi/test/integration/pack/--deps2/index.js delete mode 100755 node_modules/hapi/test/integration/pack/--deps2/package.json delete mode 100755 node_modules/hapi/test/integration/pack/--deps3/index.js delete mode 100755 node_modules/hapi/test/integration/pack/--deps3/package.json delete mode 100644 node_modules/hapi/test/integration/pack/--loaded/package.json delete mode 100755 node_modules/hapi/test/integration/pack/--skip/package.json delete mode 100755 node_modules/hapi/test/integration/pack/--test1/package.json delete mode 100755 node_modules/hapi/test/integration/pack/--test2/package.json delete mode 100755 node_modules/hapi/test/integration/pack/--views/package.json delete mode 100755 node_modules/hapi/test/integration/pack/--views/templates/test.html delete mode 100755 node_modules/hapi/test/integration/payload.js delete mode 100755 node_modules/hapi/test/integration/prerequisites.js delete mode 100755 node_modules/hapi/test/integration/proxy.js delete mode 100755 node_modules/hapi/test/integration/request.js delete mode 100755 node_modules/hapi/test/integration/response.js delete mode 100755 node_modules/hapi/test/integration/route.js delete mode 100755 node_modules/hapi/test/integration/router.js delete mode 100755 node_modules/hapi/test/integration/security.js delete mode 100755 node_modules/hapi/test/integration/server.js delete mode 100755 node_modules/hapi/test/integration/serverTimeout.js delete mode 100755 node_modules/hapi/test/unit/auth.js delete mode 100755 node_modules/hapi/test/unit/client.js delete mode 100755 node_modules/hapi/test/unit/ext.js delete mode 100755 node_modules/hapi/test/unit/payload.js delete mode 100755 node_modules/hapi/test/unit/request.js delete mode 100755 node_modules/hapi/test/unit/response/directory.js delete mode 100755 node_modules/hapi/test/unit/response/view.js delete mode 100755 node_modules/hapi/test/unit/route.js delete mode 100755 node_modules/hapi/test/unit/schema.js delete mode 100755 node_modules/hapi/test/unit/server.js delete mode 100755 node_modules/hapi/test/unit/state.js delete mode 100755 node_modules/hapi/test/unit/templates/invalid/badmustache.html delete mode 100755 node_modules/hapi/test/unit/templates/invalid/test.html delete mode 100755 node_modules/hapi/test/unit/templates/layout.html delete mode 100755 node_modules/hapi/test/unit/templates/valid/handler.html delete mode 100755 node_modules/hapi/test/unit/templates/valid/helpers/uppercase.js delete mode 100644 node_modules/hapi/test/unit/templates/valid/index.jade delete mode 100644 node_modules/hapi/test/unit/templates/valid/layout.jade delete mode 100755 node_modules/hapi/test/unit/templates/valid/partials/nav.html delete mode 100755 node_modules/hapi/test/unit/templates/valid/partials/nested/nav.html delete mode 100755 node_modules/hapi/test/unit/templates/valid/test.html delete mode 100644 node_modules/hapi/test/unit/templates/valid/test.jade delete mode 100755 node_modules/hapi/test/unit/templates/valid/testHelpers.html delete mode 100755 node_modules/hapi/test/unit/templates/valid/testMulti.jade delete mode 100755 node_modules/hapi/test/unit/templates/valid/testPartials.html delete mode 100755 node_modules/hapi/test/unit/utils.js delete mode 100755 node_modules/hapi/test/unit/validation.js delete mode 100755 node_modules/hapi/test/unit/views.js delete mode 100644 node_modules/lout/.npmignore delete mode 100755 node_modules/lout/.travis.yml delete mode 100644 node_modules/lout/AUTHORS delete mode 100755 node_modules/lout/LICENSE delete mode 100644 node_modules/lout/Makefile delete mode 100755 node_modules/lout/README.md delete mode 100755 node_modules/lout/images/lout.png delete mode 100755 node_modules/lout/index.js delete mode 100644 node_modules/lout/package.json delete mode 100644 node_modules/lout/templates/index.html delete mode 100644 node_modules/lout/templates/route.html delete mode 100755 node_modules/lout/test/index.js create mode 100644 templates/index.html diff --git a/routes.js b/backend.js similarity index 69% rename from routes.js rename to backend.js index 18227d0..c9822f3 100755 --- a/routes.js +++ b/backend.js @@ -1,10 +1,9 @@ -var Types = require('hapi').types; +var Types = require('Joi'); var ua = require('universal-analytics'); var visitor = ua('UA-27923958-9'); var Datastore = require('nedb'); - db = {}; db.runners = new Datastore({ filename: 'db/runners', autoload: true }); db.laps = new Datastore({ filename: 'db/laps', autoload: true }); @@ -13,24 +12,19 @@ module.exports = [{ method: 'GET', path: '/runners', config: { - handler: getRunners, - validate: { - payload: { - bid: Types.String() - } - } + handler: getRunners } }, { method: 'POST', path: '/runners', config: { handler: addRunner, - payload: 'parse', validate: { payload: { - bid: Types.String().required().min(3), - name: Types.String().required().min(3), - team: Types.String() + bid: Types.string().required().min(3), + name: Types.string().required().min(3), + start_time: Types.date(), + team: Types.string() } } } @@ -38,28 +32,37 @@ module.exports = [{ method: 'GET', path: '/laps', config: { - handler: getLaps, - payload: 'parse', - validate: { - payload: { - bid: Types.String().required().min(3) - } - } + handler: getLaps } }, { method: 'POST', path: '/laps', config: { - handler: addLap, - payload: 'parse', + handler: addLapRequest, validate: { payload: { - bid: Types.String().required().min(3), + bid: Types.string().required().min(3), } } } }]; +module.exports.addLap = function addLap(bid, callback){ + var lap = { + bid: bid, + time: new Date() + }; + db.laps.insert(lap, callback); + visitor.event({ + ec:'Runner Tracking', + ea:'Runner Passed', + el: lap.time, + ev: lap.bid + }, function (err) { + if (err){console.log(err)}; + }); +} + function getRunners(request) { if (request.query.bid) { getRunner(request) @@ -75,10 +78,6 @@ function getRunners(request) { } function getRunner(request) { - // var runner = runners.filter(function(p) { - // return p.id === parseInt(request.params.id); - // }).pop(); - db.runners.findOne({ bid: request.query.bid }, function (err, runner) { if (err) { console.log(err); @@ -92,6 +91,7 @@ function addRunner(request) { var runner = { bid: request.payload.bid, name: request.payload.name, + start_time:request.payload.team, team:request.payload.team }; @@ -114,27 +114,12 @@ function getLaps(request) { }); } -function addLap(request) { - var lap = { - bid: request.payload.bid, - time: new Date() - }; - visitor.event({ - ec:'Runner Tracking', - ea:'Runner Passed', - el: lap.bid, - ev: lap.time - }, function (err) { - if (err){console.log(err)}; - }); - - db.laps.insert(lap, function (err, newLap) { +function addLapRequest(request) { + exports.addLap(bid, function(err, newLap){ if (err) { console.log(err); } else { request.reply(newLap).code(200); } - }); - - + }); } \ No newline at end of file diff --git a/bluetooth.js b/bluetooth.js new file mode 100755 index 0000000..a959775 --- /dev/null +++ b/bluetooth.js @@ -0,0 +1,54 @@ +var noble = require('noble'); +var backend = require('./backend'); + + +function addLap (bid) { + backend.addLap(bid, function(err, newLap){ + if (err) { + console.log(err); + } else { + // + } + }); +} + +noble.on('stateChange', function(state) { + if (state === 'poweredOn') { + noble.startScanning([],true); + } else { + noble.stopScanning([],true); + } +}); + +var inRange = []; + +var WINDOW = 5000; // milliseconds + +noble.on('discover', function(peripheral) { + + var uuid = peripheral.uuid; + + if (!inRange[uuid]) { + inRange[uuid] = { + peripheral: peripheral + }; + addLap(uuid); + } + + inRange[uuid].lastSeen = Date.now(); +}); + +setInterval(function() { + for (var uuid in inRange) { + + console.log (inRange[uuid].peripheral.rssi, inRange[uuid].peripheral.uuid); + + if (inRange[uuid].lastSeen < (Date.now() - WINDOW)) { + console.log ('out of window', uuid); + + delete inRange[uuid]; + } + + } +}, WINDOW/10); + diff --git a/frontend.js b/frontend.js new file mode 100755 index 0000000..1e9a4b1 --- /dev/null +++ b/frontend.js @@ -0,0 +1,8 @@ +module.exports = [ +{ + method: 'GET', + path: '/', + handler: function (request, reply) { + reply.view('index', { test:'paolo' }); + } +}]; diff --git a/images/banjo.png b/images/banjo.png deleted file mode 100755 index a44581f7df51397cb63a9feca11e982a3da115c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65215 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 ICBFv#AJ|toJOBUy diff --git a/images/headers.png b/images/headers.png deleted file mode 100755 index 433ac14897514ffcb09b78a202204284ddcc8d21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 177568 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

x!y8DY6fc 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
    {{#posts}}
  • {{{link_to}}}
  • {{/posts}}
" +var source = "
    {{#posts}}
  • {{link_to}}
  • {{/posts}}
" var template = Handlebars.compile(source); template(context); @@ -99,7 +110,7 @@ templates easier and also changes a tiny detail of how partials work. ### Paths Handlebars.js supports an extended expression syntax that we call paths. -Paths are made up of typical expressions and . characters. Expressions +Paths are made up of typical expressions and `.` characters. Expressions allow you to not only display data from the current context, but to display data from contexts that are descendants and ancestors of the current context. @@ -108,7 +119,7 @@ To display data from descendant contexts, use the `.` character. So, for example, if your data were structured like: ```js -var data = {"person": { "name": "Alan" }, company: {"name": "Rad, Inc." } }; +var data = {"person": { "name": "Alan" }, "company": {"name": "Rad, Inc." } }; ``` You could display the person's name from the top-level context with the @@ -123,7 +134,7 @@ into the person object you could still display the company's name with an expression like `{{../company.name}}`, so: ``` -{{#person}}{{name}} - {{../company.name}}{{/person}} +{{#with person}}{{name}} - {{../company.name}}{{/with}} ``` would render: @@ -186,7 +197,7 @@ template(data); ``` Whenever the block helper is called it is given one or more parameters, -any arguments that are passed in the helper in the call and an `options` +any arguments that are passed into the helper in the call, and an `options` object containing the `fn` function which executes the block's child. The block's current context may be accessed through `this`. @@ -225,6 +236,35 @@ template(data); // ``` +Partials can also accept parameters + +```js +var source = "
{{> roster rosterProperties people=listOfPeople}}
"; + +Handlebars.registerPartial('roster', '

{{rosterName}}

{{#people}}{{id}}: {{name}}{{/people}}') +var template = Handlebars.compile(source); + +var data = { + "listOfPeople": [ + { "name": "Alan", "id": 1 }, + { "name": "Yehuda", "id": 2 } + ], + "rosterProperties": { + "rosterName": "Cool People" + } +}; + +template(data); + +// Should render: +//
+//

Cool People

+// 1: Alan +// 2: Yehuda +//
+ +``` + ### Comments You can add comments to your templates with the following syntax: @@ -243,6 +283,14 @@ You can also use real html comments if you want them to end up in the output. ``` +### Compatibility + +There are a few Mustache behaviors that Handlebars does not implement. +- Handlebars deviates from Mustache slightly in that it does not perform recursive lookup by default. The compile time `compat` flag must be set to enable this functionality. Users should note that there is a performance cost for enabling this flag. The exact cost varies by template, but it's recommended that performance sensitive operations should avoid this mode and instead opt for explicit path references. +- The optional Mustache-style lambdas are not supported. Instead Handlebars provides it's own lambda resolution that follows the behaviors of helpers. +- Alternative delimeters are not supported. + + Precompiling Templates ---------------------- @@ -260,13 +308,20 @@ Precompile handlebar templates. Usage: handlebars template... Options: - -a, --amd Create an AMD format function (allows loading with RequireJS) [boolean] - -f, --output Output File [string] - -k, --known Known helpers [string] - -o, --knownOnly Known helpers only [boolean] - -m, --min Minimize output [boolean] - -s, --simple Output template function only. [boolean] - -r, --root Template root. Base value that will be stripped from template names. [string] + -a, --amd Create an AMD format function (allows loading with RequireJS) [boolean] + -f, --output Output File [string] + -k, --known Known helpers [string] + -o, --knownOnly Known helpers only [boolean] + -m, --min Minimize output [boolean] + -s, --simple Output template function only. [boolean] + -r, --root Template root. Base value that will be stripped from template names. [string] + -c, --commonjs Exports CommonJS style, path to Handlebars module [string] + -h, --handlebarPath Path to handlebar.js (only valid for amd-style) [string] + -n, --namespace Template namespace [string] + -p, --partial Compiling a partial template [boolean] + -d, --data Include data when compiling [boolean] + -e, --extension Template extension. [string] + -b, --bom Removes the BOM (Byte Order Mark) from the beginning of the templates. [boolean] If using the precompiler's normal mode, the resulting templates will be @@ -275,9 +330,8 @@ name sans the extension. These templates may be executed in the same manner as templates. If using the simple mode the precompiler will generate a single -javascript method. To execute this method it must be passed to the using -the `Handlebars.template` method and the resulting object may be as -normal. +javascript method. To execute this method it must be passed to +the `Handlebars.template` method and the resulting object may be used as normal. ### Optimizations @@ -289,6 +343,8 @@ normal. helpers for size and speed. - When all helpers are known in advance the `--knownOnly` argument may be used to optimize all block helper references. +- Implementations that do not use `@data` variables can improve performance of + iteration centric templates by specifying `{data: false}` in the compiler options. Supported Environments ---------------------- @@ -303,7 +359,9 @@ Handlebars has been designed to work in any ECMAScript 3 environment. This inclu - IE 6+ Older versions and other runtimes are likely to work but have not been formally -tested. +tested. The compiler requires `JSON.stringify` to be implemented natively or via a polyfill. If using the precompiler this is not necessary. + +[![Selenium Test Status](https://saucelabs.com/browser-matrix/handlebars.svg)](https://saucelabs.com/u/handlebars) Performance ----------- @@ -316,14 +374,7 @@ does have some big performance advantages. Justin Marney, a.k.a. [gotascii](http://github.com/gotascii), confirmed that with an [independent test](http://sorescode.com/2010/09/12/benchmarks.html). The rewritten Handlebars (current version) is faster than the old version, -and we will have some benchmarks in the near future. - - -Building --------- - -To build handlebars, just run `rake release`, and you will get two files -in the `dist` directory. +with many [performance tests](https://travis-ci.org/wycats/handlebars.js/builds/33392182#L538) being 5 to 7 times faster than the Mustache equivalent. Upgrading @@ -333,59 +384,55 @@ See [release-notes.md](https://github.com/wycats/handlebars.js/blob/master/relea Known Issues ------------ -* Handlebars.js can be cryptic when there's an error while rendering. -* Using a variable, helper, or partial named `class` causes errors in IE browsers. (Instead, use `className`) + +See [FAQ.md](https://github.com/wycats/handlebars.js/blob/master/FAQ.md) for known issues and common pitfalls. + Handlebars in the Wild ------------------ +---------------------- + +* [Assemble](http://assemble.io), by [@jonschlinkert](https://github.com/jonschlinkert) + and [@doowb](https://github.com/doowb), is a static site generator that uses Handlebars.js + as its template engine. +* [CoSchedule](http://coschedule.com) An editorial calendar for WordPress that uses Handlebars.js +* [dashbars](https://github.com/pismute/dashbars) A modern helper library for Handlebars.js. +* [Ember.js](http://www.emberjs.com) makes Handlebars.js the primary way to + structure your views, also with automatic data binding support. +* [Ghost](https://ghost.org/) Just a blogging platform. +* [handlebars_assets](http://github.com/leshill/handlebars_assets): A Rails Asset Pipeline gem + from Les Hill (@leshill). +* [handlebars-helpers](https://github.com/assemble/handlebars-helpers) is an extensive library + with 100+ handlebars helpers. +* [handlebars-layouts](https://github.com/shannonmoeller/handlebars-layouts) is a set of helpers which implement extendible and embeddable layout blocks as seen in other popular templating languages. +* [hbs](http://github.com/donpark/hbs): An Express.js view engine adapter for Handlebars.js, + from Don Park. +* [koa-hbs](https://github.com/jwilm/koa-hbs): [koa](https://github.com/koajs/koa) generator based + renderer for Handlebars.js. * [jblotus](http://github.com/jblotus) created [http://tryhandlebarsjs.com](http://tryhandlebarsjs.com) for anyone who would like to try out Handlebars.js in their browser. -* Don Park wrote an Express.js view engine adapter for Handlebars.js called - [hbs](http://github.com/donpark/hbs). +* [jQuery plugin](http://71104.github.io/jquery-handlebars/): allows you to use + Handlebars.js with [jQuery](http://jquery.com/). +* [Lumbar](http://walmartlabs.github.io/lumbar) provides easy module-based template management for + handlebars projects. * [sammy.js](http://github.com/quirkey/sammy) by Aaron Quint, a.k.a. quirkey, supports Handlebars.js as one of its template plugins. * [SproutCore](http://www.sproutcore.com) uses Handlebars.js as its main templating engine, extending it with automatic data binding support. -* [Ember.js](http://www.emberjs.com) makes Handlebars.js the primary way to - structure your views, also with automatic data binding support. -* Les Hill (@leshill) wrote a Rails Asset Pipeline gem named - [handlebars_assets](http://github.com/leshill/handlebars_assets). -* [Gist about Synchronous and asynchronous loading of external handlebars templates](https://gist.github.com/2287070) -* [Lumbar](walmartlabs.github.io/lumbar) provides easy module-based template management for handlebars projects. * [YUI](http://yuilibrary.com/yui/docs/handlebars/) implements a port of handlebars +* [Swag](https://github.com/elving/swag) by [@elving](https://github.com/elving) is a growing collection of helpers for handlebars.js. Give your handlebars.js templates some swag son! +* [DOMBars](https://github.com/blakeembrey/dombars) is a DOM-based templating engine built on the Handlebars parser and runtime -Have a project using Handlebars? Send us a [pull request](https://github.com/wycats/handlebars.js/pull/new/master)! - -Helping Out ------------ -To build Handlebars.js you'll need a few things installed. +External Resources +------------------ -* Node.js -* Ruby -* therubyracer, for running tests - `gem install therubyracer` -* rspec, for running tests - `gem install rspec` - -There's a Gemfile in the repo, so you can run `bundle` to install rspec -and therubyracer if you've got bundler installed. - -To build Handlebars.js from scratch, you'll want to run `rake compile` -in the root of the project. That will build Handlebars and output the -results to the dist/ folder. To run tests, run `rake test`. You can also -run our set of benchmarks with `rake bench`. Node tests can be run with -`npm test` or `rake npm_test`. The default rake target will compile and -run both test suites. - -Some environments, notably Windows, have issues running therubyracer. Under these -envrionments the `rake compile` and `npm test` should be sufficient to test -most handlebars functionality. +* [Gist about Synchronous and asynchronous loading of external handlebars templates](https://gist.github.com/2287070) -If you notice any problems, please report them to the GitHub issue tracker at -[http://github.com/wycats/handlebars.js/issues](http://github.com/wycats/handlebars.js/issues). -Feel free to contact commondream or wycats through GitHub with any other -questions or feature requests. To submit changes fork the project and -send a pull request. +Have a project using Handlebars? Send us a [pull request][pull-request]! License ------- Handlebars.js is released under the MIT license. +[bower-repo]: https://github.com/components/handlebars.js +[builds-page]: http://builds.handlebarsjs.com.s3.amazonaws.com/bucket-listing.html?sort=lastmod&sortdir=desc +[pull-request]: https://github.com/wycats/handlebars.js/pull/new/master diff --git a/node_modules/handlebars/bin/handlebars b/node_modules/handlebars/bin/handlebars index 4835770..4ed98b3 100755 --- a/node_modules/handlebars/bin/handlebars +++ b/node_modules/handlebars/bin/handlebars @@ -1,12 +1,16 @@ #!/usr/bin/env node var optimist = require('optimist') - .usage('Precompile handlebar templates.\nUsage: $0 template...', { + .usage('Precompile handlebar templates.\nUsage: $0 [template|directory]...', { 'f': { 'type': 'string', 'description': 'Output File', 'alias': 'output' }, + 'map': { + 'type': 'string', + 'description': 'Source Map File' + }, 'a': { 'type': 'boolean', 'description': 'Exports amd style (require.js)', @@ -22,7 +26,7 @@ var optimist = require('optimist') 'type': 'string', 'description': 'Path to handlebar.js (only valid for amd-style)', 'alias': 'handlebarPath', - 'default': '' + 'default': '' }, 'k': { 'type': 'string', @@ -70,144 +74,38 @@ var optimist = require('optimist') 'description': 'Template extension.', 'alias': 'extension', 'default': 'handlebars' - } - }) + }, + 'b': { + 'type': 'boolean', + 'description': 'Removes the BOM (Byte Order Mark) from the beginning of the templates.', + 'alias': 'bom' + }, + 'v': { + 'type': 'boolean', + 'description': 'Prints the current compiler version', + 'alias': 'version' + }, - .check(function(argv) { - var template = [0]; - if (!argv._.length) { - throw 'Must define at least one template or directory.'; + 'help': { + 'type': 'boolean', + 'description': 'Outputs this message' } - - argv._.forEach(function(template) { - try { - fs.statSync(template); - } catch (err) { - throw 'Unable to open template file "' + template + '"'; - } - }); }) - .check(function(argv) { - if (argv.simple && argv.min) { - throw 'Unable to minimze simple output'; - } - if (argv.simple && (argv._.length !== 1 || fs.statSync(argv._[0]).isDirectory())) { - throw 'Unable to output multiple templates in simple mode'; - } - }); - -var fs = require('fs'), - handlebars = require('../lib/handlebars'), - basename = require('path').basename, - uglify = require('uglify-js'); - -var argv = optimist.argv, - template = argv._[0]; -// Convert the known list into a hash -var known = {}; -if (argv.known && !Array.isArray(argv.known)) { - argv.known = [argv.known]; -} -if (argv.known) { - for (var i = 0, len = argv.known.length; i < len; i++) { - known[argv.known[i]] = true; - } -} - -// Build file extension pattern -var extension = argv.extension.replace(/[\\^$*+?.():=!|{}\-\[\]]/g, function(arg) { return '\\' + arg; }); -extension = new RegExp('\\.' + extension + '$'); - -var output = []; -if (!argv.simple) { - if (argv.amd) { - output.push('define([\'' + argv.handlebarPath + 'handlebars\'], function(Handlebars) {\n'); - } else if (argv.commonjs) { - output.push('var Handlebars = require("' + argv.commonjs + '");'); - } else { - output.push('(function() {\n'); - } - output.push(' var template = Handlebars.template, templates = '); - output.push(argv.namespace); - output.push(' = '); - output.push(argv.namespace); - output.push(' || {};\n'); -} -function processTemplate(template, root) { - var path = template, - stat = fs.statSync(path); - if (stat.isDirectory()) { - fs.readdirSync(template).map(function(file) { - var path = template + '/' + file; - - if (extension.test(path) || fs.statSync(path).isDirectory()) { - processTemplate(path, root || template); + .check(function(argv) { + if (argv.version) { + return; } }); - } else { - var data = fs.readFileSync(path, 'utf8'); - var options = { - knownHelpers: known, - knownHelpersOnly: argv.o - }; - if (argv.data) { - options.data = true; - } +var argv = optimist.argv; +argv.templates = argv._; +delete argv._; - // Clean the template name - if (!root) { - template = basename(template); - } else if (template.indexOf(root) === 0) { - template = template.substring(root.length+1); - } - template = template.replace(extension, ''); - - if (argv.simple) { - output.push(handlebars.precompile(data, options) + '\n'); - } else if (argv.partial) { - if(argv.amd && (argv._.length == 1 && !fs.statSync(argv._[0]).isDirectory())) { - output.push('return '); - } - output.push('Handlebars.partials[\'' + template + '\'] = template(' + handlebars.precompile(data, options) + ');\n'); - } else { - if(argv.amd && (argv._.length == 1 && !fs.statSync(argv._[0]).isDirectory())) { - output.push('return '); - } - output.push('templates[\'' + template + '\'] = template(' + handlebars.precompile(data, options) + ');\n'); - } - } -} - -argv._.forEach(function(template) { - processTemplate(template, argv.root); -}); - -// Output the content -if (!argv.simple) { - if (argv.amd) { - if(argv._.length > 1 || (argv._.length == 1 && fs.statSync(argv._[0]).isDirectory())) { - if(argv.partial){ - output.push('return Handlebars.partials;\n'); - } else { - output.push('return templates;\n'); - } - } - output.push('});'); - } else if (!argv.commonjs) { - output.push('})();'); - } -} -output = output.join(''); - -if (argv.min) { - output = uglify.minify(output, {fromString: true}).code; +if (argv.help || (!argv.templates.length && !argv.version)) { + optimist.showHelp(); + return; } -if (argv.output) { - fs.writeFileSync(argv.output, output, 'utf8'); -} else { - console.log(output); -} +return require('../dist/cjs/precompiler').cli(argv); diff --git a/node_modules/handlebars/bower.json b/node_modules/handlebars/bower.json deleted file mode 100644 index 4b86a80..0000000 --- a/node_modules/handlebars/bower.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "handlebars.js", - "version": "1.0.0", - "main": "dist/handlebars.js", - "ignore": [ - "node_modules", - "components" - ] -} diff --git a/node_modules/handlebars/global-test.js b/node_modules/handlebars/global-test.js deleted file mode 100644 index 2d5db2e..0000000 --- a/node_modules/handlebars/global-test.js +++ /dev/null @@ -1,18 +0,0 @@ -var Handlebars = require('./lib/handlebars'); - -Handlebars.registerHelper('test_helper', function() { return 'found it!' }); -Handlebars.registerPartial('global_test', '{{another_dude}}'); - -//var template = Handlebars.compile('{{test_helper}} {{#if cruel}}Goodbye {{cruel}} {{world}}!{{/if}}'); -var template = Handlebars.precompile("Dudes: {{#if foo}} {{#if nested}} {{> shared/dude}} {{/if}} {{> global_test}} {{/if}}"); -console.log(template); - -return; - -console.log( - template({cruel: "cruel", name:"Jeepers", another_dude:"Creepers"}, { - helpers: {world: function() { return "world!"; }}, - partials: {'shared/dude':"{{name}}"} - })); - -console.log(template); diff --git a/node_modules/handlebars/global.js b/node_modules/handlebars/global.js deleted file mode 100644 index 20c185c..0000000 --- a/node_modules/handlebars/global.js +++ /dev/null @@ -1,4 +0,0 @@ -var Handlebars = require('./lib/handlebars'); - -var template = Handlebars.compile('{{#if unless}}foo{{/if}}'); -console.log(template({ foo: function() { return 'bar'; } })); diff --git a/node_modules/handlebars/handlebars-source.gemspec b/node_modules/handlebars/handlebars-source.gemspec deleted file mode 100644 index 514e2b1..0000000 --- a/node_modules/handlebars/handlebars-source.gemspec +++ /dev/null @@ -1,21 +0,0 @@ -# -*- encoding: utf-8 -*- -require 'json' - -package = JSON.parse(File.read('package.json')) - -Gem::Specification.new do |gem| - gem.name = "handlebars-source" - gem.authors = ["Yehuda Katz"] - gem.email = ["wycats@gmail.com"] - gem.date = Time.now.strftime("%Y-%m-%d") - gem.description = %q{Handlebars.js source code wrapper for (pre)compilation gems.} - gem.summary = %q{Handlebars.js source code wrapper} - gem.homepage = "https://github.com/wycats/handlebars.js/" - gem.version = package["version"] - - gem.files = [ - 'dist/handlebars.js', - 'dist/handlebars.runtime.js', - 'lib/handlebars/source.rb' - ] -end diff --git a/node_modules/handlebars/handlebars.js.nuspec b/node_modules/handlebars/handlebars.js.nuspec deleted file mode 100644 index 4515f2e..0000000 --- a/node_modules/handlebars/handlebars.js.nuspec +++ /dev/null @@ -1,17 +0,0 @@ - - - - handlebars.js - 1.0.0 - handlebars.js Authors - https://github.com/wycats/handlebars.js/blob/master/LICENSE - https://github.com/wycats/handlebars.js/ - false - Extension of the Mustache logicless template language - - handlebars mustache template html - - - - - diff --git a/node_modules/handlebars/min.sh b/node_modules/handlebars/min.sh deleted file mode 100755 index aba5da9..0000000 --- a/node_modules/handlebars/min.sh +++ /dev/null @@ -1,11 +0,0 @@ -rm dist/* - -rake - -for x in dist/*.js; do - x=${x%.*} - uglifyjs -c -m -- $x.js > $x.min.js - gzip -c $x.min.js > $x.min.js.gz -done - -ls -l dist | awk '{ print $9 " " $5 }' diff --git a/node_modules/handlebars/node_modules/optimist/index.js b/node_modules/handlebars/node_modules/optimist/index.js index 8ac67eb..4da5a6d 100644 --- a/node_modules/handlebars/node_modules/optimist/index.js +++ b/node_modules/handlebars/node_modules/optimist/index.js @@ -1,4 +1,5 @@ var path = require('path'); +var minimist = require('minimist'); var wordwrap = require('wordwrap'); /* Hack an instance of Argv with process.argv into Argv @@ -17,7 +18,7 @@ Object.keys(inst).forEach(function (key) { }); var exports = module.exports = Argv; -function Argv (args, cwd) { +function Argv (processArgs, cwd) { var self = {}; if (!cwd) cwd = process.cwd(); @@ -37,50 +38,44 @@ function Argv (args, cwd) { ); } - var flags = { bools : {}, strings : {} }; + var options = { + boolean: [], + string: [], + alias: {}, + default: [] + }; self.boolean = function (bools) { - if (!Array.isArray(bools)) { - bools = [].slice.call(arguments); - } - - bools.forEach(function (name) { - flags.bools[name] = true; - }); - + options.boolean.push.apply(options.boolean, [].concat(bools)); return self; }; self.string = function (strings) { - if (!Array.isArray(strings)) { - strings = [].slice.call(arguments); + options.string.push.apply(options.string, [].concat(strings)); + return self; + }; + + self.default = function (key, value) { + if (typeof key === 'object') { + Object.keys(key).forEach(function (k) { + self.default(k, key[k]); + }); + } + else { + options.default[key] = value; } - - strings.forEach(function (name) { - flags.strings[name] = true; - }); - return self; }; - var aliases = {}; self.alias = function (x, y) { if (typeof x === 'object') { Object.keys(x).forEach(function (key) { self.alias(key, x[key]); }); } - else if (Array.isArray(y)) { - y.forEach(function (yy) { - self.alias(x, yy); - }); - } else { - var zs = (aliases[x] || []).concat(aliases[y] || []).concat(x, y); - aliases[x] = zs.filter(function (z) { return z != x }); - aliases[y] = zs.filter(function (z) { return z != y }); + options.alias[x] = (options.alias[x] || []).concat(y); } - return self; }; @@ -128,20 +123,6 @@ function Argv (args, cwd) { return self; }; - var defaults = {}; - self.default = function (key, value) { - if (typeof key === 'object') { - Object.keys(key).forEach(function (k) { - self.default(k, key[k]); - }); - } - else { - defaults[key] = value; - } - - return self; - }; - var descriptions = {}; self.describe = function (key, desc) { if (typeof key === 'object') { @@ -156,7 +137,7 @@ function Argv (args, cwd) { }; self.parse = function (args) { - return Argv(args).argv; + return parseArgs(args); }; self.option = self.options = function (key, opt) { @@ -203,7 +184,7 @@ function Argv (args, cwd) { var keys = Object.keys( Object.keys(descriptions) .concat(Object.keys(demanded)) - .concat(Object.keys(defaults)) + .concat(Object.keys(options.default)) .reduce(function (acc, key) { if (key !== '_') acc[key] = true; return acc; @@ -217,7 +198,7 @@ function Argv (args, cwd) { } var switches = keys.reduce(function (acc, key) { - acc[key] = [ key ].concat(aliases[key] || []) + acc[key] = [ key ].concat(options.alias[key] || []) .map(function (sw) { return (sw.length > 1 ? '--' : '-') + sw }) @@ -254,8 +235,8 @@ function Argv (args, cwd) { var type = null; - if (flags.bools[key]) type = '[boolean]'; - if (flags.strings[key]) type = '[string]'; + if (options.boolean[key]) type = '[boolean]'; + if (options.string[key]) type = '[string]'; if (!wrap && dpadding.length > 0) { desc += dpadding; @@ -268,8 +249,8 @@ function Argv (args, cwd) { ? '[required]' : null , - defaults[key] !== undefined - ? '[default: ' + JSON.stringify(defaults[key]) + ']' + options.default[key] !== undefined + ? '[default: ' + JSON.stringify(options.default[key]) + ']' : null , ].filter(Boolean).join(' '); @@ -298,110 +279,13 @@ function Argv (args, cwd) { }; Object.defineProperty(self, 'argv', { - get : parseArgs, + get : function () { return parseArgs(processArgs) }, enumerable : true, }); - function parseArgs () { - var argv = { _ : [], $0 : self.$0 }; - Object.keys(flags.bools).forEach(function (key) { - setArg(key, defaults[key] || false); - }); - - function setArg (key, val) { - var num = Number(val); - var value = typeof val !== 'string' || isNaN(num) ? val : num; - if (flags.strings[key]) value = val; - - setKey(argv, key.split('.'), value); - - (aliases[key] || []).forEach(function (x) { - argv[x] = argv[key]; - }); - } - - for (var i = 0; i < args.length; i++) { - var arg = args[i]; - - if (arg === '--') { - argv._.push.apply(argv._, args.slice(i + 1)); - break; - } - else if (arg.match(/^--.+=/)) { - // Using [\s\S] instead of . because js doesn't support the - // 'dotall' regex modifier. See: - // http://stackoverflow.com/a/1068308/13216 - var m = arg.match(/^--([^=]+)=([\s\S]*)$/); - setArg(m[1], m[2]); - } - else if (arg.match(/^--no-.+/)) { - var key = arg.match(/^--no-(.+)/)[1]; - setArg(key, false); - } - else if (arg.match(/^--.+/)) { - var key = arg.match(/^--(.+)/)[1]; - var next = args[i + 1]; - if (next !== undefined && !next.match(/^-/) - && !flags.bools[key] - && (aliases[key] ? !flags.bools[aliases[key]] : true)) { - setArg(key, next); - i++; - } - else if (/^(true|false)$/.test(next)) { - setArg(key, next === 'true'); - i++; - } - else { - setArg(key, true); - } - } - else if (arg.match(/^-[^-]+/)) { - var letters = arg.slice(1,-1).split(''); - - var broken = false; - for (var j = 0; j < letters.length; j++) { - if (letters[j+1] && letters[j+1].match(/\W/)) { - setArg(letters[j], arg.slice(j+2)); - broken = true; - break; - } - else { - setArg(letters[j], true); - } - } - - if (!broken) { - var key = arg.slice(-1)[0]; - - if (args[i+1] && !args[i+1].match(/^-/) - && !flags.bools[key] - && (aliases[key] ? !flags.bools[aliases[key]] : true)) { - setArg(key, args[i+1]); - i++; - } - else if (args[i+1] && /true|false/.test(args[i+1])) { - setArg(key, args[i+1] === 'true'); - i++; - } - else { - setArg(key, true); - } - } - } - else { - var n = Number(arg); - argv._.push(flags.strings['_'] || isNaN(n) ? arg : n); - } - } - - Object.keys(defaults).forEach(function (key) { - if (!(key in argv)) { - argv[key] = defaults[key]; - if (key in aliases) { - argv[aliases[key]] = defaults[key]; - } - } - }); + function parseArgs (args) { + var argv = minimist(args, options); + argv.$0 = self.$0; if (demanded._ && argv._.length < demanded._) { fail('Not enough non-option arguments: got ' @@ -457,22 +341,3 @@ function rebase (base, dir) { ).replace(/\/$/,'').replace(/^$/, '.'); return p.match(/^[.\/]/) ? p : './' + p; }; - -function setKey (obj, keys, value) { - var o = obj; - keys.slice(0,-1).forEach(function (key) { - if (o[key] === undefined) o[key] = {}; - o = o[key]; - }); - - var key = keys[keys.length - 1]; - if (o[key] === undefined || typeof o[key] === 'boolean') { - o[key] = value; - } - else if (Array.isArray(o[key])) { - o[key].push(value); - } - else { - o[key] = [ o[key], value ]; - } -} diff --git a/node_modules/handlebars/node_modules/optimist/package.json b/node_modules/handlebars/node_modules/optimist/package.json index ab63c9c..54ee844 100644 --- a/node_modules/handlebars/node_modules/optimist/package.json +++ b/node_modules/handlebars/node_modules/optimist/package.json @@ -1,10 +1,11 @@ { "name": "optimist", - "version": "0.3.7", + "version": "0.6.1", "description": "Light-weight option parsing with an argv hash. No optstrings attached.", "main": "./index.js", "dependencies": { - "wordwrap": "~0.0.2" + "wordwrap": "~0.0.2", + "minimist": "~0.0.1" }, "devDependencies": { "hashish": "~0.0.4", @@ -35,12 +36,12 @@ "engine": { "node": ">=0.4" }, - "readme": "optimist\n========\n\nOptimist is a node.js library for option parsing for people who hate option\nparsing. More specifically, this module is for people who like all the --bells\nand -whistlz of program usage but think optstrings are a waste of time.\n\nWith optimist, option parsing doesn't have to suck (as much).\n\n[![build status](https://secure.travis-ci.org/substack/node-optimist.png)](http://travis-ci.org/substack/node-optimist)\n\nexamples\n========\n\nWith Optimist, the options are just a hash! No optstrings attached.\n-------------------------------------------------------------------\n\nxup.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\n\nif (argv.rif - 5 * argv.xup > 7.138) {\n console.log('Buy more riffiwobbles');\n}\nelse {\n console.log('Sell the xupptumblers');\n}\n````\n\n***\n\n $ ./xup.js --rif=55 --xup=9.52\n Buy more riffiwobbles\n \n $ ./xup.js --rif 12 --xup 8.1\n Sell the xupptumblers\n\n![This one's optimistic.](http://substack.net/images/optimistic.png)\n\nBut wait! There's more! You can do short options:\n-------------------------------------------------\n \nshort.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\nconsole.log('(%d,%d)', argv.x, argv.y);\n````\n\n***\n\n $ ./short.js -x 10 -y 21\n (10,21)\n\nAnd booleans, both long and short (and grouped):\n----------------------------------\n\nbool.js:\n\n````javascript\n#!/usr/bin/env node\nvar util = require('util');\nvar argv = require('optimist').argv;\n\nif (argv.s) {\n util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: ');\n}\nconsole.log(\n (argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '')\n);\n````\n\n***\n\n $ ./bool.js -s\n The cat says: meow\n \n $ ./bool.js -sp\n The cat says: meow.\n\n $ ./bool.js -sp --fr\n Le chat dit: miaou.\n\nAnd non-hypenated options too! Just use `argv._`!\n-------------------------------------------------\n \nnonopt.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\nconsole.log('(%d,%d)', argv.x, argv.y);\nconsole.log(argv._);\n````\n\n***\n\n $ ./nonopt.js -x 6.82 -y 3.35 moo\n (6.82,3.35)\n [ 'moo' ]\n \n $ ./nonopt.js foo -x 0.54 bar -y 1.12 baz\n (0.54,1.12)\n [ 'foo', 'bar', 'baz' ]\n\nPlus, Optimist comes with .usage() and .demand()!\n-------------------------------------------------\n\ndivide.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .usage('Usage: $0 -x [num] -y [num]')\n .demand(['x','y'])\n .argv;\n\nconsole.log(argv.x / argv.y);\n````\n\n***\n \n $ ./divide.js -x 55 -y 11\n 5\n \n $ node ./divide.js -x 4.91 -z 2.51\n Usage: node ./divide.js -x [num] -y [num]\n\n Options:\n -x [required]\n -y [required]\n\n Missing required arguments: y\n\nEVEN MORE HOLY COW\n------------------\n\ndefault_singles.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .default('x', 10)\n .default('y', 10)\n .argv\n;\nconsole.log(argv.x + argv.y);\n````\n\n***\n\n $ ./default_singles.js -x 5\n 15\n\ndefault_hash.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .default({ x : 10, y : 10 })\n .argv\n;\nconsole.log(argv.x + argv.y);\n````\n\n***\n\n $ ./default_hash.js -y 7\n 17\n\nAnd if you really want to get all descriptive about it...\n---------------------------------------------------------\n\nboolean_single.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .boolean('v')\n .argv\n;\nconsole.dir(argv);\n````\n\n***\n\n $ ./boolean_single.js -v foo bar baz\n true\n [ 'bar', 'baz', 'foo' ]\n\nboolean_double.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .boolean(['x','y','z'])\n .argv\n;\nconsole.dir([ argv.x, argv.y, argv.z ]);\nconsole.dir(argv._);\n````\n\n***\n\n $ ./boolean_double.js -x -z one two three\n [ true, false, true ]\n [ 'one', 'two', 'three' ]\n\nOptimist is here to help...\n---------------------------\n\nYou can describe parameters for help messages and set aliases. Optimist figures\nout how to format a handy help string automatically.\n\nline_count.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .usage('Count the lines in a file.\\nUsage: $0')\n .demand('f')\n .alias('f', 'file')\n .describe('f', 'Load a file')\n .argv\n;\n\nvar fs = require('fs');\nvar s = fs.createReadStream(argv.file);\n\nvar lines = 0;\ns.on('data', function (buf) {\n lines += buf.toString().match(/\\n/g).length;\n});\n\ns.on('end', function () {\n console.log(lines);\n});\n````\n\n***\n\n $ node line_count.js\n Count the lines in a file.\n Usage: node ./line_count.js\n\n Options:\n -f, --file Load a file [required]\n\n Missing required arguments: f\n\n $ node line_count.js --file line_count.js \n 20\n \n $ node line_count.js -f line_count.js \n 20\n\nmethods\n=======\n\nBy itself,\n\n````javascript\nrequire('optimist').argv\n`````\n\nwill use `process.argv` array to construct the `argv` object.\n\nYou can pass in the `process.argv` yourself:\n\n````javascript\nrequire('optimist')([ '-x', '1', '-y', '2' ]).argv\n````\n\nor use .parse() to do the same thing:\n\n````javascript\nrequire('optimist').parse([ '-x', '1', '-y', '2' ])\n````\n\nThe rest of these methods below come in just before the terminating `.argv`.\n\n.alias(key, alias)\n------------------\n\nSet key names as equivalent such that updates to a key will propagate to aliases\nand vice-versa.\n\nOptionally `.alias()` can take an object that maps keys to aliases.\n\n.default(key, value)\n--------------------\n\nSet `argv[key]` to `value` if no option was specified on `process.argv`.\n\nOptionally `.default()` can take an object that maps keys to default values.\n\n.demand(key)\n------------\n\nIf `key` is a string, show the usage information and exit if `key` wasn't\nspecified in `process.argv`.\n\nIf `key` is a number, demand at least as many non-option arguments, which show\nup in `argv._`.\n\nIf `key` is an Array, demand each element.\n\n.describe(key, desc)\n--------------------\n\nDescribe a `key` for the generated usage information.\n\nOptionally `.describe()` can take an object that maps keys to descriptions.\n\n.options(key, opt)\n------------------\n\nInstead of chaining together `.alias().demand().default()`, you can specify\nkeys in `opt` for each of the chainable methods.\n\nFor example:\n\n````javascript\nvar argv = require('optimist')\n .options('f', {\n alias : 'file',\n default : '/etc/passwd',\n })\n .argv\n;\n````\n\nis the same as\n\n````javascript\nvar argv = require('optimist')\n .alias('f', 'file')\n .default('f', '/etc/passwd')\n .argv\n;\n````\n\nOptionally `.options()` can take an object that maps keys to `opt` parameters.\n\n.usage(message)\n---------------\n\nSet a usage message to show which commands to use. Inside `message`, the string\n`$0` will get interpolated to the current script name or node command for the\npresent script similar to how `$0` works in bash or perl.\n\n.check(fn)\n----------\n\nCheck that certain conditions are met in the provided arguments.\n\nIf `fn` throws or returns `false`, show the thrown error, usage information, and\nexit.\n\n.boolean(key)\n-------------\n\nInterpret `key` as a boolean. If a non-flag option follows `key` in\n`process.argv`, that string won't get set as the value of `key`.\n\nIf `key` never shows up as a flag in `process.arguments`, `argv[key]` will be\n`false`.\n\nIf `key` is an Array, interpret all the elements as booleans.\n\n.string(key)\n------------\n\nTell the parser logic not to interpret `key` as a number or boolean.\nThis can be useful if you need to preserve leading zeros in an input.\n\nIf `key` is an Array, interpret all the elements as strings.\n\n.wrap(columns)\n--------------\n\nFormat usage output to wrap at `columns` many columns.\n\n.help()\n-------\n\nReturn the generated usage string.\n\n.showHelp(fn=console.error)\n---------------------------\n\nPrint the usage data using `fn` for printing.\n\n.parse(args)\n------------\n\nParse `args` instead of `process.argv`. Returns the `argv` object.\n\n.argv\n-----\n\nGet the arguments as a plain old object.\n\nArguments without a corresponding flag show up in the `argv._` array.\n\nThe script name or node command is available at `argv.$0` similarly to how `$0`\nworks in bash or perl.\n\nparsing tricks\n==============\n\nstop parsing\n------------\n\nUse `--` to stop parsing flags and stuff the remainder into `argv._`.\n\n $ node examples/reflect.js -a 1 -b 2 -- -c 3 -d 4\n { _: [ '-c', '3', '-d', '4' ],\n '$0': 'node ./examples/reflect.js',\n a: 1,\n b: 2 }\n\nnegate fields\n-------------\n\nIf you want to explicity set a field to false instead of just leaving it\nundefined or to override a default you can do `--no-key`.\n\n $ node examples/reflect.js -a --no-b\n { _: [],\n '$0': 'node ./examples/reflect.js',\n a: true,\n b: false }\n\nnumbers\n-------\n\nEvery argument that looks like a number (`!isNaN(Number(arg))`) is converted to\none. This way you can just `net.createConnection(argv.port)` and you can add\nnumbers out of `argv` with `+` without having that mean concatenation,\nwhich is super frustrating.\n\nduplicates\n----------\n\nIf you specify a flag multiple times it will get turned into an array containing\nall the values in order.\n\n $ node examples/reflect.js -x 5 -x 8 -x 0\n { _: [],\n '$0': 'node ./examples/reflect.js',\n x: [ 5, 8, 0 ] }\n\ndot notation\n------------\n\nWhen you use dots (`.`s) in argument names, an implicit object path is assumed.\nThis lets you organize arguments into nested objects.\n\n $ node examples/reflect.js --foo.bar.baz=33 --foo.quux=5\n { _: [],\n '$0': 'node ./examples/reflect.js',\n foo: { bar: { baz: 33 }, quux: 5 } }\n\ninstallation\n============\n\nWith [npm](http://github.com/isaacs/npm), just do:\n npm install optimist\n \nor clone this project on github:\n\n git clone http://github.com/substack/node-optimist.git\n\nTo run the tests with [expresso](http://github.com/visionmedia/expresso),\njust do:\n \n expresso\n\ninspired By\n===========\n\nThis module is loosely inspired by Perl's\n[Getopt::Casual](http://search.cpan.org/~photo/Getopt-Casual-0.13.1/Casual.pm).\n", + "readme": "# DEPRECATION NOTICE\n\nI don't want to maintain this module anymore since I just use\n[minimist](https://npmjs.org/package/minimist), the argument parsing engine,\ndirectly instead nowadays.\n\nSee [yargs](https://github.com/chevex/yargs) for the modern, pirate-themed\nsuccessor to optimist.\n\n[![yarrrrrrrgs!](http://i.imgur.com/4WFGVJ9.png)](https://github.com/chevex/yargs)\n\nYou should also consider [nomnom](https://github.com/harthur/nomnom).\n\noptimist\n========\n\nOptimist is a node.js library for option parsing for people who hate option\nparsing. More specifically, this module is for people who like all the --bells\nand -whistlz of program usage but think optstrings are a waste of time.\n\nWith optimist, option parsing doesn't have to suck (as much).\n\n[![build status](https://secure.travis-ci.org/substack/node-optimist.png)](http://travis-ci.org/substack/node-optimist)\n\nexamples\n========\n\nWith Optimist, the options are just a hash! No optstrings attached.\n-------------------------------------------------------------------\n\nxup.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\n\nif (argv.rif - 5 * argv.xup > 7.138) {\n console.log('Buy more riffiwobbles');\n}\nelse {\n console.log('Sell the xupptumblers');\n}\n````\n\n***\n\n $ ./xup.js --rif=55 --xup=9.52\n Buy more riffiwobbles\n \n $ ./xup.js --rif 12 --xup 8.1\n Sell the xupptumblers\n\n![This one's optimistic.](http://substack.net/images/optimistic.png)\n\nBut wait! There's more! You can do short options:\n-------------------------------------------------\n \nshort.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\nconsole.log('(%d,%d)', argv.x, argv.y);\n````\n\n***\n\n $ ./short.js -x 10 -y 21\n (10,21)\n\nAnd booleans, both long and short (and grouped):\n----------------------------------\n\nbool.js:\n\n````javascript\n#!/usr/bin/env node\nvar util = require('util');\nvar argv = require('optimist').argv;\n\nif (argv.s) {\n util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: ');\n}\nconsole.log(\n (argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '')\n);\n````\n\n***\n\n $ ./bool.js -s\n The cat says: meow\n \n $ ./bool.js -sp\n The cat says: meow.\n\n $ ./bool.js -sp --fr\n Le chat dit: miaou.\n\nAnd non-hypenated options too! Just use `argv._`!\n-------------------------------------------------\n \nnonopt.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\nconsole.log('(%d,%d)', argv.x, argv.y);\nconsole.log(argv._);\n````\n\n***\n\n $ ./nonopt.js -x 6.82 -y 3.35 moo\n (6.82,3.35)\n [ 'moo' ]\n \n $ ./nonopt.js foo -x 0.54 bar -y 1.12 baz\n (0.54,1.12)\n [ 'foo', 'bar', 'baz' ]\n\nPlus, Optimist comes with .usage() and .demand()!\n-------------------------------------------------\n\ndivide.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .usage('Usage: $0 -x [num] -y [num]')\n .demand(['x','y'])\n .argv;\n\nconsole.log(argv.x / argv.y);\n````\n\n***\n \n $ ./divide.js -x 55 -y 11\n 5\n \n $ node ./divide.js -x 4.91 -z 2.51\n Usage: node ./divide.js -x [num] -y [num]\n\n Options:\n -x [required]\n -y [required]\n\n Missing required arguments: y\n\nEVEN MORE HOLY COW\n------------------\n\ndefault_singles.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .default('x', 10)\n .default('y', 10)\n .argv\n;\nconsole.log(argv.x + argv.y);\n````\n\n***\n\n $ ./default_singles.js -x 5\n 15\n\ndefault_hash.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .default({ x : 10, y : 10 })\n .argv\n;\nconsole.log(argv.x + argv.y);\n````\n\n***\n\n $ ./default_hash.js -y 7\n 17\n\nAnd if you really want to get all descriptive about it...\n---------------------------------------------------------\n\nboolean_single.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .boolean('v')\n .argv\n;\nconsole.dir(argv);\n````\n\n***\n\n $ ./boolean_single.js -v foo bar baz\n true\n [ 'bar', 'baz', 'foo' ]\n\nboolean_double.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .boolean(['x','y','z'])\n .argv\n;\nconsole.dir([ argv.x, argv.y, argv.z ]);\nconsole.dir(argv._);\n````\n\n***\n\n $ ./boolean_double.js -x -z one two three\n [ true, false, true ]\n [ 'one', 'two', 'three' ]\n\nOptimist is here to help...\n---------------------------\n\nYou can describe parameters for help messages and set aliases. Optimist figures\nout how to format a handy help string automatically.\n\nline_count.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .usage('Count the lines in a file.\\nUsage: $0')\n .demand('f')\n .alias('f', 'file')\n .describe('f', 'Load a file')\n .argv\n;\n\nvar fs = require('fs');\nvar s = fs.createReadStream(argv.file);\n\nvar lines = 0;\ns.on('data', function (buf) {\n lines += buf.toString().match(/\\n/g).length;\n});\n\ns.on('end', function () {\n console.log(lines);\n});\n````\n\n***\n\n $ node line_count.js\n Count the lines in a file.\n Usage: node ./line_count.js\n\n Options:\n -f, --file Load a file [required]\n\n Missing required arguments: f\n\n $ node line_count.js --file line_count.js \n 20\n \n $ node line_count.js -f line_count.js \n 20\n\nmethods\n=======\n\nBy itself,\n\n````javascript\nrequire('optimist').argv\n`````\n\nwill use `process.argv` array to construct the `argv` object.\n\nYou can pass in the `process.argv` yourself:\n\n````javascript\nrequire('optimist')([ '-x', '1', '-y', '2' ]).argv\n````\n\nor use .parse() to do the same thing:\n\n````javascript\nrequire('optimist').parse([ '-x', '1', '-y', '2' ])\n````\n\nThe rest of these methods below come in just before the terminating `.argv`.\n\n.alias(key, alias)\n------------------\n\nSet key names as equivalent such that updates to a key will propagate to aliases\nand vice-versa.\n\nOptionally `.alias()` can take an object that maps keys to aliases.\n\n.default(key, value)\n--------------------\n\nSet `argv[key]` to `value` if no option was specified on `process.argv`.\n\nOptionally `.default()` can take an object that maps keys to default values.\n\n.demand(key)\n------------\n\nIf `key` is a string, show the usage information and exit if `key` wasn't\nspecified in `process.argv`.\n\nIf `key` is a number, demand at least as many non-option arguments, which show\nup in `argv._`.\n\nIf `key` is an Array, demand each element.\n\n.describe(key, desc)\n--------------------\n\nDescribe a `key` for the generated usage information.\n\nOptionally `.describe()` can take an object that maps keys to descriptions.\n\n.options(key, opt)\n------------------\n\nInstead of chaining together `.alias().demand().default()`, you can specify\nkeys in `opt` for each of the chainable methods.\n\nFor example:\n\n````javascript\nvar argv = require('optimist')\n .options('f', {\n alias : 'file',\n default : '/etc/passwd',\n })\n .argv\n;\n````\n\nis the same as\n\n````javascript\nvar argv = require('optimist')\n .alias('f', 'file')\n .default('f', '/etc/passwd')\n .argv\n;\n````\n\nOptionally `.options()` can take an object that maps keys to `opt` parameters.\n\n.usage(message)\n---------------\n\nSet a usage message to show which commands to use. Inside `message`, the string\n`$0` will get interpolated to the current script name or node command for the\npresent script similar to how `$0` works in bash or perl.\n\n.check(fn)\n----------\n\nCheck that certain conditions are met in the provided arguments.\n\nIf `fn` throws or returns `false`, show the thrown error, usage information, and\nexit.\n\n.boolean(key)\n-------------\n\nInterpret `key` as a boolean. If a non-flag option follows `key` in\n`process.argv`, that string won't get set as the value of `key`.\n\nIf `key` never shows up as a flag in `process.arguments`, `argv[key]` will be\n`false`.\n\nIf `key` is an Array, interpret all the elements as booleans.\n\n.string(key)\n------------\n\nTell the parser logic not to interpret `key` as a number or boolean.\nThis can be useful if you need to preserve leading zeros in an input.\n\nIf `key` is an Array, interpret all the elements as strings.\n\n.wrap(columns)\n--------------\n\nFormat usage output to wrap at `columns` many columns.\n\n.help()\n-------\n\nReturn the generated usage string.\n\n.showHelp(fn=console.error)\n---------------------------\n\nPrint the usage data using `fn` for printing.\n\n.parse(args)\n------------\n\nParse `args` instead of `process.argv`. Returns the `argv` object.\n\n.argv\n-----\n\nGet the arguments as a plain old object.\n\nArguments without a corresponding flag show up in the `argv._` array.\n\nThe script name or node command is available at `argv.$0` similarly to how `$0`\nworks in bash or perl.\n\nparsing tricks\n==============\n\nstop parsing\n------------\n\nUse `--` to stop parsing flags and stuff the remainder into `argv._`.\n\n $ node examples/reflect.js -a 1 -b 2 -- -c 3 -d 4\n { _: [ '-c', '3', '-d', '4' ],\n '$0': 'node ./examples/reflect.js',\n a: 1,\n b: 2 }\n\nnegate fields\n-------------\n\nIf you want to explicity set a field to false instead of just leaving it\nundefined or to override a default you can do `--no-key`.\n\n $ node examples/reflect.js -a --no-b\n { _: [],\n '$0': 'node ./examples/reflect.js',\n a: true,\n b: false }\n\nnumbers\n-------\n\nEvery argument that looks like a number (`!isNaN(Number(arg))`) is converted to\none. This way you can just `net.createConnection(argv.port)` and you can add\nnumbers out of `argv` with `+` without having that mean concatenation,\nwhich is super frustrating.\n\nduplicates\n----------\n\nIf you specify a flag multiple times it will get turned into an array containing\nall the values in order.\n\n $ node examples/reflect.js -x 5 -x 8 -x 0\n { _: [],\n '$0': 'node ./examples/reflect.js',\n x: [ 5, 8, 0 ] }\n\ndot notation\n------------\n\nWhen you use dots (`.`s) in argument names, an implicit object path is assumed.\nThis lets you organize arguments into nested objects.\n\n $ node examples/reflect.js --foo.bar.baz=33 --foo.quux=5\n { _: [],\n '$0': 'node ./examples/reflect.js',\n foo: { bar: { baz: 33 }, quux: 5 } }\n\nshort numbers\n-------------\n\nShort numeric `head -n5` style argument work too:\n\n $ node reflect.js -n123 -m456\n { '3': true,\n '6': true,\n _: [],\n '$0': 'node ./reflect.js',\n n: 123,\n m: 456 }\n\ninstallation\n============\n\nWith [npm](http://github.com/isaacs/npm), just do:\n npm install optimist\n \nor clone this project on github:\n\n git clone http://github.com/substack/node-optimist.git\n\nTo run the tests with [expresso](http://github.com/visionmedia/expresso),\njust do:\n \n expresso\n\ninspired By\n===========\n\nThis module is loosely inspired by Perl's\n[Getopt::Casual](http://search.cpan.org/~photo/Getopt-Casual-0.13.1/Casual.pm).\n", "readmeFilename": "readme.markdown", "bugs": { "url": "https://github.com/substack/node-optimist/issues" }, "homepage": "https://github.com/substack/node-optimist", - "_id": "optimist@0.3.7", - "_from": "optimist@>=0.3.0 <0.4.0" + "_id": "optimist@0.6.1", + "_from": "optimist@>=0.6.1 <0.7.0" } diff --git a/node_modules/handlebars/node_modules/optimist/readme.markdown b/node_modules/handlebars/node_modules/optimist/readme.markdown index ad9d3fd..b74b437 100644 --- a/node_modules/handlebars/node_modules/optimist/readme.markdown +++ b/node_modules/handlebars/node_modules/optimist/readme.markdown @@ -1,3 +1,16 @@ +# DEPRECATION NOTICE + +I don't want to maintain this module anymore since I just use +[minimist](https://npmjs.org/package/minimist), the argument parsing engine, +directly instead nowadays. + +See [yargs](https://github.com/chevex/yargs) for the modern, pirate-themed +successor to optimist. + +[![yarrrrrrrgs!](http://i.imgur.com/4WFGVJ9.png)](https://github.com/chevex/yargs) + +You should also consider [nomnom](https://github.com/harthur/nomnom). + optimist ======== @@ -465,6 +478,19 @@ This lets you organize arguments into nested objects. '$0': 'node ./examples/reflect.js', foo: { bar: { baz: 33 }, quux: 5 } } +short numbers +------------- + +Short numeric `head -n5` style argument work too: + + $ node reflect.js -n123 -m456 + { '3': true, + '6': true, + _: [], + '$0': 'node ./reflect.js', + n: 123, + m: 456 } + installation ============ diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/.npmignore b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/.npmignore deleted file mode 100644 index 3dddf3f..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -dist/* -node_modules/* diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/.travis.yml b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/.travis.yml deleted file mode 100644 index ddc9c4f..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/.travis.yml +++ /dev/null @@ -1,4 +0,0 @@ -language: node_js -node_js: - - 0.8 - - "0.10" \ No newline at end of file diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/CHANGELOG.md b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/CHANGELOG.md deleted file mode 100644 index 2e7ca5d..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/CHANGELOG.md +++ /dev/null @@ -1,194 +0,0 @@ -# Change Log - -## 0.1.43 - -* Performance improvements for `SourceMapGenerator` and `SourceNode`. See issue - #148 for some discussion and issues #150, #151, and #152 for implementations. - -## 0.1.42 - -* Fix an issue where `SourceNode`s from different versions of the source-map - library couldn't be used in conjunction with each other. See issue #142. - -## 0.1.41 - -* Fix a bug with getting the source content of relative sources with a "./" - prefix. See issue #145 and [Bug 1090768](bugzil.la/1090768). - -* Add the `SourceMapConsumer.prototype.computeColumnSpans` method to compute the - column span of each mapping. - -* Add the `SourceMapConsumer.prototype.allGeneratedPositionsFor` method to find - all generated positions associated with a given original source and line. - -## 0.1.40 - -* Performance improvements for parsing source maps in SourceMapConsumer. - -## 0.1.39 - -* Fix a bug where setting a source's contents to null before any source content - had been set before threw a TypeError. See issue #131. - -## 0.1.38 - -* Fix a bug where finding relative paths from an empty path were creating - absolute paths. See issue #129. - -## 0.1.37 - -* Fix a bug where if the source root was an empty string, relative source paths - would turn into absolute source paths. Issue #124. - -## 0.1.36 - -* Allow the `names` mapping property to be an empty string. Issue #121. - -## 0.1.35 - -* A third optional parameter was added to `SourceNode.fromStringWithSourceMap` - to specify a path that relative sources in the second parameter should be - relative to. Issue #105. - -* If no file property is given to a `SourceMapGenerator`, then the resulting - source map will no longer have a `null` file property. The property will - simply not exist. Issue #104. - -* Fixed a bug where consecutive newlines were ignored in `SourceNode`s. - Issue #116. - -## 0.1.34 - -* Make `SourceNode` work with windows style ("\r\n") newlines. Issue #103. - -* Fix bug involving source contents and the - `SourceMapGenerator.prototype.applySourceMap`. Issue #100. - -## 0.1.33 - -* Fix some edge cases surrounding path joining and URL resolution. - -* Add a third parameter for relative path to - `SourceMapGenerator.prototype.applySourceMap`. - -* Fix issues with mappings and EOLs. - -## 0.1.32 - -* Fixed a bug where SourceMapConsumer couldn't handle negative relative columns - (issue 92). - -* Fixed test runner to actually report number of failed tests as its process - exit code. - -* Fixed a typo when reporting bad mappings (issue 87). - -## 0.1.31 - -* Delay parsing the mappings in SourceMapConsumer until queried for a source - location. - -* Support Sass source maps (which at the time of writing deviate from the spec - in small ways) in SourceMapConsumer. - -## 0.1.30 - -* Do not join source root with a source, when the source is a data URI. - -* Extend the test runner to allow running single specific test files at a time. - -* Performance improvements in `SourceNode.prototype.walk` and - `SourceMapConsumer.prototype.eachMapping`. - -* Source map browser builds will now work inside Workers. - -* Better error messages when attempting to add an invalid mapping to a - `SourceMapGenerator`. - -## 0.1.29 - -* Allow duplicate entries in the `names` and `sources` arrays of source maps - (usually from TypeScript) we are parsing. Fixes github issue 72. - -## 0.1.28 - -* Skip duplicate mappings when creating source maps from SourceNode; github - issue 75. - -## 0.1.27 - -* Don't throw an error when the `file` property is missing in SourceMapConsumer, - we don't use it anyway. - -## 0.1.26 - -* Fix SourceNode.fromStringWithSourceMap for empty maps. Fixes github issue 70. - -## 0.1.25 - -* Make compatible with browserify - -## 0.1.24 - -* Fix issue with absolute paths and `file://` URIs. See - https://bugzilla.mozilla.org/show_bug.cgi?id=885597 - -## 0.1.23 - -* Fix issue with absolute paths and sourcesContent, github issue 64. - -## 0.1.22 - -* Ignore duplicate mappings in SourceMapGenerator. Fixes github issue 21. - -## 0.1.21 - -* Fixed handling of sources that start with a slash so that they are relative to - the source root's host. - -## 0.1.20 - -* Fixed github issue #43: absolute URLs aren't joined with the source root - anymore. - -## 0.1.19 - -* Using Travis CI to run tests. - -## 0.1.18 - -* Fixed a bug in the handling of sourceRoot. - -## 0.1.17 - -* Added SourceNode.fromStringWithSourceMap. - -## 0.1.16 - -* Added missing documentation. - -* Fixed the generating of empty mappings in SourceNode. - -## 0.1.15 - -* Added SourceMapGenerator.applySourceMap. - -## 0.1.14 - -* The sourceRoot is now handled consistently. - -## 0.1.13 - -* Added SourceMapGenerator.fromSourceMap. - -## 0.1.12 - -* SourceNode now generates empty mappings too. - -## 0.1.11 - -* Added name support to SourceNode. - -## 0.1.10 - -* Added sourcesContent support to the customer and generator. diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/LICENSE b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/LICENSE deleted file mode 100644 index ed1b7cf..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/LICENSE +++ /dev/null @@ -1,28 +0,0 @@ - -Copyright (c) 2009-2011, Mozilla Foundation and contributors -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the names of the Mozilla Foundation nor the names of project - contributors may be used to endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/Makefile.dryice.js b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/Makefile.dryice.js deleted file mode 100644 index d6fc26a..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/Makefile.dryice.js +++ /dev/null @@ -1,166 +0,0 @@ -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ -var path = require('path'); -var fs = require('fs'); -var copy = require('dryice').copy; - -function removeAmdefine(src) { - src = String(src).replace( - /if\s*\(typeof\s*define\s*!==\s*'function'\)\s*{\s*var\s*define\s*=\s*require\('amdefine'\)\(module,\s*require\);\s*}\s*/g, - ''); - src = src.replace( - /\b(define\(.*)('amdefine',?)/gm, - '$1'); - return src; -} -removeAmdefine.onRead = true; - -function makeNonRelative(src) { - return src - .replace(/require\('.\//g, 'require(\'source-map/') - .replace(/\.\.\/\.\.\/lib\//g, ''); -} -makeNonRelative.onRead = true; - -function buildBrowser() { - console.log('\nCreating dist/source-map.js'); - - var project = copy.createCommonJsProject({ - roots: [ path.join(__dirname, 'lib') ] - }); - - copy({ - source: [ - 'build/mini-require.js', - { - project: project, - require: [ 'source-map/source-map-generator', - 'source-map/source-map-consumer', - 'source-map/source-node'] - }, - 'build/suffix-browser.js' - ], - filter: [ - copy.filter.moduleDefines, - removeAmdefine - ], - dest: 'dist/source-map.js' - }); -} - -function buildBrowserMin() { - console.log('\nCreating dist/source-map.min.js'); - - copy({ - source: 'dist/source-map.js', - filter: copy.filter.uglifyjs, - dest: 'dist/source-map.min.js' - }); -} - -function buildFirefox() { - console.log('\nCreating dist/SourceMap.jsm'); - - var project = copy.createCommonJsProject({ - roots: [ path.join(__dirname, 'lib') ] - }); - - copy({ - source: [ - 'build/prefix-source-map.jsm', - { - project: project, - require: [ 'source-map/source-map-consumer', - 'source-map/source-map-generator', - 'source-map/source-node' ] - }, - 'build/suffix-source-map.jsm' - ], - filter: [ - copy.filter.moduleDefines, - removeAmdefine, - makeNonRelative - ], - dest: 'dist/SourceMap.jsm' - }); - - // Create dist/test/Utils.jsm - console.log('\nCreating dist/test/Utils.jsm'); - - project = copy.createCommonJsProject({ - roots: [ __dirname, path.join(__dirname, 'lib') ] - }); - - copy({ - source: [ - 'build/prefix-utils.jsm', - 'build/assert-shim.js', - { - project: project, - require: [ 'test/source-map/util' ] - }, - 'build/suffix-utils.jsm' - ], - filter: [ - copy.filter.moduleDefines, - removeAmdefine, - makeNonRelative - ], - dest: 'dist/test/Utils.jsm' - }); - - function isTestFile(f) { - return /^test\-.*?\.js/.test(f); - } - - var testFiles = fs.readdirSync(path.join(__dirname, 'test', 'source-map')).filter(isTestFile); - - testFiles.forEach(function (testFile) { - console.log('\nCreating', path.join('dist', 'test', testFile.replace(/\-/g, '_'))); - - copy({ - source: [ - 'build/test-prefix.js', - path.join('test', 'source-map', testFile), - 'build/test-suffix.js' - ], - filter: [ - removeAmdefine, - makeNonRelative, - function (input, source) { - return input.replace('define(', - 'define("' - + path.join('test', 'source-map', testFile.replace(/\.js$/, '')) - + '", ["require", "exports", "module"], '); - }, - function (input, source) { - return input.replace('{THIS_MODULE}', function () { - return "test/source-map/" + testFile.replace(/\.js$/, ''); - }); - } - ], - dest: path.join('dist', 'test', testFile.replace(/\-/g, '_')) - }); - }); -} - -function ensureDir(name) { - var dirExists = false; - try { - dirExists = fs.statSync(name).isDirectory(); - } catch (err) {} - - if (!dirExists) { - fs.mkdirSync(name, 0777); - } -} - -ensureDir("dist"); -ensureDir("dist/test"); -buildFirefox(); -buildBrowser(); -buildBrowserMin(); diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/README.md b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/README.md deleted file mode 100644 index 59767aa..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/README.md +++ /dev/null @@ -1,475 +0,0 @@ -# Source Map - -This is a library to generate and consume the source map format -[described here][format]. - -This library is written in the Asynchronous Module Definition format, and works -in the following environments: - -* Modern Browsers supporting ECMAScript 5 (either after the build, or with an - AMD loader such as RequireJS) - -* Inside Firefox (as a JSM file, after the build) - -* With NodeJS versions 0.8.X and higher - -## Node - - $ npm install source-map - -## Building from Source (for everywhere else) - -Install Node and then run - - $ git clone https://fitzgen@github.com/mozilla/source-map.git - $ cd source-map - $ npm link . - -Next, run - - $ node Makefile.dryice.js - -This should spew a bunch of stuff to stdout, and create the following files: - -* `dist/source-map.js` - The unminified browser version. - -* `dist/source-map.min.js` - The minified browser version. - -* `dist/SourceMap.jsm` - The JavaScript Module for inclusion in Firefox source. - -## Examples - -### Consuming a source map - - var rawSourceMap = { - version: 3, - file: 'min.js', - names: ['bar', 'baz', 'n'], - sources: ['one.js', 'two.js'], - sourceRoot: 'http://example.com/www/js/', - mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' - }; - - var smc = new SourceMapConsumer(rawSourceMap); - - console.log(smc.sources); - // [ 'http://example.com/www/js/one.js', - // 'http://example.com/www/js/two.js' ] - - console.log(smc.originalPositionFor({ - line: 2, - column: 28 - })); - // { source: 'http://example.com/www/js/two.js', - // line: 2, - // column: 10, - // name: 'n' } - - console.log(smc.generatedPositionFor({ - source: 'http://example.com/www/js/two.js', - line: 2, - column: 10 - })); - // { line: 2, column: 28 } - - smc.eachMapping(function (m) { - // ... - }); - -### Generating a source map - -In depth guide: -[**Compiling to JavaScript, and Debugging with Source Maps**](https://hacks.mozilla.org/2013/05/compiling-to-javascript-and-debugging-with-source-maps/) - -#### With SourceNode (high level API) - - function compile(ast) { - switch (ast.type) { - case 'BinaryExpression': - return new SourceNode( - ast.location.line, - ast.location.column, - ast.location.source, - [compile(ast.left), " + ", compile(ast.right)] - ); - case 'Literal': - return new SourceNode( - ast.location.line, - ast.location.column, - ast.location.source, - String(ast.value) - ); - // ... - default: - throw new Error("Bad AST"); - } - } - - var ast = parse("40 + 2", "add.js"); - console.log(compile(ast).toStringWithSourceMap({ - file: 'add.js' - })); - // { code: '40 + 2', - // map: [object SourceMapGenerator] } - -#### With SourceMapGenerator (low level API) - - var map = new SourceMapGenerator({ - file: "source-mapped.js" - }); - - map.addMapping({ - generated: { - line: 10, - column: 35 - }, - source: "foo.js", - original: { - line: 33, - column: 2 - }, - name: "christopher" - }); - - console.log(map.toString()); - // '{"version":3,"file":"source-mapped.js","sources":["foo.js"],"names":["christopher"],"mappings":";;;;;;;;;mCAgCEA"}' - -## API - -Get a reference to the module: - - // NodeJS - var sourceMap = require('source-map'); - - // Browser builds - var sourceMap = window.sourceMap; - - // Inside Firefox - let sourceMap = {}; - Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap); - -### SourceMapConsumer - -A SourceMapConsumer instance represents a parsed source map which we can query -for information about the original file positions by giving it a file position -in the generated source. - -#### new SourceMapConsumer(rawSourceMap) - -The only parameter is the raw source map (either as a string which can be -`JSON.parse`'d, or an object). According to the spec, source maps have the -following attributes: - -* `version`: Which version of the source map spec this map is following. - -* `sources`: An array of URLs to the original source files. - -* `names`: An array of identifiers which can be referrenced by individual - mappings. - -* `sourceRoot`: Optional. The URL root from which all sources are relative. - -* `sourcesContent`: Optional. An array of contents of the original source files. - -* `mappings`: A string of base64 VLQs which contain the actual mappings. - -* `file`: Optional. The generated filename this source map is associated with. - -#### SourceMapConsumer.prototype.computeColumnSpans() - -Compute the last column for each generated mapping. The last column is -inclusive. - -#### SourceMapConsumer.prototype.originalPositionFor(generatedPosition) - -Returns the original source, line, and column information for the generated -source's line and column positions provided. The only argument is an object with -the following properties: - -* `line`: The line number in the generated source. - -* `column`: The column number in the generated source. - -and an object is returned with the following properties: - -* `source`: The original source file, or null if this information is not - available. - -* `line`: The line number in the original source, or null if this information is - not available. - -* `column`: The column number in the original source, or null or null if this - information is not available. - -* `name`: The original identifier, or null if this information is not available. - -#### SourceMapConsumer.prototype.generatedPositionFor(originalPosition) - -Returns the generated line and column information for the original source, -line, and column positions provided. The only argument is an object with -the following properties: - -* `source`: The filename of the original source. - -* `line`: The line number in the original source. - -* `column`: The column number in the original source. - -and an object is returned with the following properties: - -* `line`: The line number in the generated source, or null. - -* `column`: The column number in the generated source, or null. - -#### SourceMapConsumer.prototype.allGeneratedPositionsFor(originalPosition) - -Returns all generated line and column information for the original source -and line provided. The only argument is an object with the following -properties: - -* `source`: The filename of the original source. - -* `line`: The line number in the original source. - -and an array of objects is returned, each with the following properties: - -* `line`: The line number in the generated source, or null. - -* `column`: The column number in the generated source, or null. - -#### SourceMapConsumer.prototype.sourceContentFor(source) - -Returns the original source content for the source provided. The only -argument is the URL of the original source file. - -#### SourceMapConsumer.prototype.eachMapping(callback, context, order) - -Iterate over each mapping between an original source/line/column and a -generated line/column in this source map. - -* `callback`: The function that is called with each mapping. Mappings have the - form `{ source, generatedLine, generatedColumn, originalLine, originalColumn, - name }` - -* `context`: Optional. If specified, this object will be the value of `this` - every time that `callback` is called. - -* `order`: Either `SourceMapConsumer.GENERATED_ORDER` or - `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to iterate over - the mappings sorted by the generated file's line/column order or the - original's source/line/column order, respectively. Defaults to - `SourceMapConsumer.GENERATED_ORDER`. - -### SourceMapGenerator - -An instance of the SourceMapGenerator represents a source map which is being -built incrementally. - -#### new SourceMapGenerator([startOfSourceMap]) - -You may pass an object with the following properties: - -* `file`: The filename of the generated source that this source map is - associated with. - -* `sourceRoot`: A root for all relative URLs in this source map. - -* `skipValidation`: Optional. When `true`, disables validation of mappings as - they are added. This can improve performance but should be used with - discretion, as a last resort. Even then, one should avoid using this flag when - running tests, if possible. - -#### SourceMapGenerator.fromSourceMap(sourceMapConsumer) - -Creates a new SourceMapGenerator based on a SourceMapConsumer - -* `sourceMapConsumer` The SourceMap. - -#### SourceMapGenerator.prototype.addMapping(mapping) - -Add a single mapping from original source line and column to the generated -source's line and column for this source map being created. The mapping object -should have the following properties: - -* `generated`: An object with the generated line and column positions. - -* `original`: An object with the original line and column positions. - -* `source`: The original source file (relative to the sourceRoot). - -* `name`: An optional original token name for this mapping. - -#### SourceMapGenerator.prototype.setSourceContent(sourceFile, sourceContent) - -Set the source content for an original source file. - -* `sourceFile` the URL of the original source file. - -* `sourceContent` the content of the source file. - -#### SourceMapGenerator.prototype.applySourceMap(sourceMapConsumer[, sourceFile[, sourceMapPath]]) - -Applies a SourceMap for a source file to the SourceMap. -Each mapping to the supplied source file is rewritten using the -supplied SourceMap. Note: The resolution for the resulting mappings -is the minimium of this map and the supplied map. - -* `sourceMapConsumer`: The SourceMap to be applied. - -* `sourceFile`: Optional. The filename of the source file. - If omitted, sourceMapConsumer.file will be used, if it exists. - Otherwise an error will be thrown. - -* `sourceMapPath`: Optional. The dirname of the path to the SourceMap - to be applied. If relative, it is relative to the SourceMap. - - This parameter is needed when the two SourceMaps aren't in the same - directory, and the SourceMap to be applied contains relative source - paths. If so, those relative source paths need to be rewritten - relative to the SourceMap. - - If omitted, it is assumed that both SourceMaps are in the same directory, - thus not needing any rewriting. (Supplying `'.'` has the same effect.) - -#### SourceMapGenerator.prototype.toString() - -Renders the source map being generated to a string. - -### SourceNode - -SourceNodes provide a way to abstract over interpolating and/or concatenating -snippets of generated JavaScript source code, while maintaining the line and -column information associated between those snippets and the original source -code. This is useful as the final intermediate representation a compiler might -use before outputting the generated JS and source map. - -#### new SourceNode([line, column, source[, chunk[, name]]]) - -* `line`: The original line number associated with this source node, or null if - it isn't associated with an original line. - -* `column`: The original column number associated with this source node, or null - if it isn't associated with an original column. - -* `source`: The original source's filename; null if no filename is provided. - -* `chunk`: Optional. Is immediately passed to `SourceNode.prototype.add`, see - below. - -* `name`: Optional. The original identifier. - -#### SourceNode.fromStringWithSourceMap(code, sourceMapConsumer[, relativePath]) - -Creates a SourceNode from generated code and a SourceMapConsumer. - -* `code`: The generated code - -* `sourceMapConsumer` The SourceMap for the generated code - -* `relativePath` The optional path that relative sources in `sourceMapConsumer` - should be relative to. - -#### SourceNode.prototype.add(chunk) - -Add a chunk of generated JS to this source node. - -* `chunk`: A string snippet of generated JS code, another instance of - `SourceNode`, or an array where each member is one of those things. - -#### SourceNode.prototype.prepend(chunk) - -Prepend a chunk of generated JS to this source node. - -* `chunk`: A string snippet of generated JS code, another instance of - `SourceNode`, or an array where each member is one of those things. - -#### SourceNode.prototype.setSourceContent(sourceFile, sourceContent) - -Set the source content for a source file. This will be added to the -`SourceMap` in the `sourcesContent` field. - -* `sourceFile`: The filename of the source file - -* `sourceContent`: The content of the source file - -#### SourceNode.prototype.walk(fn) - -Walk over the tree of JS snippets in this node and its children. The walking -function is called once for each snippet of JS and is passed that snippet and -the its original associated source's line/column location. - -* `fn`: The traversal function. - -#### SourceNode.prototype.walkSourceContents(fn) - -Walk over the tree of SourceNodes. The walking function is called for each -source file content and is passed the filename and source content. - -* `fn`: The traversal function. - -#### SourceNode.prototype.join(sep) - -Like `Array.prototype.join` except for SourceNodes. Inserts the separator -between each of this source node's children. - -* `sep`: The separator. - -#### SourceNode.prototype.replaceRight(pattern, replacement) - -Call `String.prototype.replace` on the very right-most source snippet. Useful -for trimming whitespace from the end of a source node, etc. - -* `pattern`: The pattern to replace. - -* `replacement`: The thing to replace the pattern with. - -#### SourceNode.prototype.toString() - -Return the string representation of this source node. Walks over the tree and -concatenates all the various snippets together to one string. - -#### SourceNode.prototype.toStringWithSourceMap([startOfSourceMap]) - -Returns the string representation of this tree of source nodes, plus a -SourceMapGenerator which contains all the mappings between the generated and -original sources. - -The arguments are the same as those to `new SourceMapGenerator`. - -## Tests - -[![Build Status](https://travis-ci.org/mozilla/source-map.png?branch=master)](https://travis-ci.org/mozilla/source-map) - -Install NodeJS version 0.8.0 or greater, then run `node test/run-tests.js`. - -To add new tests, create a new file named `test/test-.js` -and export your test functions with names that start with "test", for example - - exports["test doing the foo bar"] = function (assert, util) { - ... - }; - -The new test will be located automatically when you run the suite. - -The `util` argument is the test utility module located at `test/source-map/util`. - -The `assert` argument is a cut down version of node's assert module. You have -access to the following assertion functions: - -* `doesNotThrow` - -* `equal` - -* `ok` - -* `strictEqual` - -* `throws` - -(The reason for the restricted set of test functions is because we need the -tests to run inside Firefox's test suite as well and so the assert module is -shimmed in that environment. See `build/assert-shim.js`.) - -[format]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit -[feature]: https://wiki.mozilla.org/DevTools/Features/SourceMap -[Dryice]: https://github.com/mozilla/dryice diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/LICENSE b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/LICENSE deleted file mode 100644 index f33d665..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/LICENSE +++ /dev/null @@ -1,58 +0,0 @@ -amdefine is released under two licenses: new BSD, and MIT. You may pick the -license that best suits your development needs. The text of both licenses are -provided below. - - -The "New" BSD License: ----------------------- - -Copyright (c) 2011, The Dojo Foundation -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Dojo Foundation nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - -MIT License ------------ - -Copyright (c) 2011, The Dojo Foundation - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/README.md b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/README.md deleted file mode 100644 index c6995c0..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/README.md +++ /dev/null @@ -1,171 +0,0 @@ -# amdefine - -A module that can be used to implement AMD's define() in Node. This allows you -to code to the AMD API and have the module work in node programs without -requiring those other programs to use AMD. - -## Usage - -**1)** Update your package.json to indicate amdefine as a dependency: - -```javascript - "dependencies": { - "amdefine": ">=0.1.0" - } -``` - -Then run `npm install` to get amdefine into your project. - -**2)** At the top of each module that uses define(), place this code: - -```javascript -if (typeof define !== 'function') { var define = require('amdefine')(module) } -``` - -**Only use these snippets** when loading amdefine. If you preserve the basic structure, -with the braces, it will be stripped out when using the [RequireJS optimizer](#optimizer). - -You can add spaces, line breaks and even require amdefine with a local path, but -keep the rest of the structure to get the stripping behavior. - -As you may know, because `if` statements in JavaScript don't have their own scope, the var -declaration in the above snippet is made whether the `if` expression is truthy or not. If -RequireJS is loaded then the declaration is superfluous because `define` is already already -declared in the same scope in RequireJS. Fortunately JavaScript handles multiple `var` -declarations of the same variable in the same scope gracefully. - -If you want to deliver amdefine.js with your code rather than specifying it as a dependency -with npm, then just download the latest release and refer to it using a relative path: - -[Latest Version](https://github.com/jrburke/amdefine/raw/latest/amdefine.js) - -### amdefine/intercept - -Consider this very experimental. - -Instead of pasting the piece of text for the amdefine setup of a `define` -variable in each module you create or consume, you can use `amdefine/intercept` -instead. It will automatically insert the above snippet in each .js file loaded -by Node. - -**Warning**: you should only use this if you are creating an application that -is consuming AMD style defined()'d modules that are distributed via npm and want -to run that code in Node. - -For library code where you are not sure if it will be used by others in Node or -in the browser, then explicitly depending on amdefine and placing the code -snippet above is suggested path, instead of using `amdefine/intercept`. The -intercept module affects all .js files loaded in the Node app, and it is -inconsiderate to modify global state like that unless you are also controlling -the top level app. - -#### Why distribute AMD-style nodes via npm? - -npm has a lot of weaknesses for front-end use (installed layout is not great, -should have better support for the `baseUrl + moduleID + '.js' style of loading, -single file JS installs), but some people want a JS package manager and are -willing to live with those constraints. If that is you, but still want to author -in AMD style modules to get dynamic require([]), better direct source usage and -powerful loader plugin support in the browser, then this tool can help. - -#### amdefine/intercept usage - -Just require it in your top level app module (for example index.js, server.js): - -```javascript -require('amdefine/intercept'); -``` - -The module does not return a value, so no need to assign the result to a local -variable. - -Then just require() code as you normally would with Node's require(). Any .js -loaded after the intercept require will have the amdefine check injected in -the .js source as it is loaded. It does not modify the source on disk, just -prepends some content to the text of the module as it is loaded by Node. - -#### How amdefine/intercept works - -It overrides the `Module._extensions['.js']` in Node to automatically prepend -the amdefine snippet above. So, it will affect any .js file loaded by your -app. - -## define() usage - -It is best if you use the anonymous forms of define() in your module: - -```javascript -define(function (require) { - var dependency = require('dependency'); -}); -``` - -or - -```javascript -define(['dependency'], function (dependency) { - -}); -``` - -## RequireJS optimizer integration. - -Version 1.0.3 of the [RequireJS optimizer](http://requirejs.org/docs/optimization.html) -will have support for stripping the `if (typeof define !== 'function')` check -mentioned above, so you can include this snippet for code that runs in the -browser, but avoid taking the cost of the if() statement once the code is -optimized for deployment. - -## Node 0.4 Support - -If you want to support Node 0.4, then add `require` as the second parameter to amdefine: - -```javascript -//Only if you want Node 0.4. If using 0.5 or later, use the above snippet. -if (typeof define !== 'function') { var define = require('amdefine')(module, require) } -``` - -## Limitations - -### Synchronous vs Asynchronous - -amdefine creates a define() function that is callable by your code. It will -execute and trace dependencies and call the factory function *synchronously*, -to keep the behavior in line with Node's synchronous dependency tracing. - -The exception: calling AMD's callback-style require() from inside a factory -function. The require callback is called on process.nextTick(): - -```javascript -define(function (require) { - require(['a'], function(a) { - //'a' is loaded synchronously, but - //this callback is called on process.nextTick(). - }); -}); -``` - -### Loader Plugins - -Loader plugins are supported as long as they call their load() callbacks -synchronously. So ones that do network requests will not work. However plugins -like [text](http://requirejs.org/docs/api.html#text) can load text files locally. - -The plugin API's `load.fromText()` is **not supported** in amdefine, so this means -transpiler plugins like the [CoffeeScript loader plugin](https://github.com/jrburke/require-cs) -will not work. This may be fixable, but it is a bit complex, and I do not have -enough node-fu to figure it out yet. See the source for amdefine.js if you want -to get an idea of the issues involved. - -## Tests - -To run the tests, cd to **tests** and run: - -``` -node all.js -node all-intercept.js -``` - -## License - -New BSD and MIT. Check the LICENSE file for all the details. diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/amdefine.js b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/amdefine.js deleted file mode 100644 index 53bf5a6..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/amdefine.js +++ /dev/null @@ -1,299 +0,0 @@ -/** vim: et:ts=4:sw=4:sts=4 - * @license amdefine 0.1.0 Copyright (c) 2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/amdefine for details - */ - -/*jslint node: true */ -/*global module, process */ -'use strict'; - -/** - * Creates a define for node. - * @param {Object} module the "module" object that is defined by Node for the - * current module. - * @param {Function} [requireFn]. Node's require function for the current module. - * It only needs to be passed in Node versions before 0.5, when module.require - * did not exist. - * @returns {Function} a define function that is usable for the current node - * module. - */ -function amdefine(module, requireFn) { - 'use strict'; - var defineCache = {}, - loaderCache = {}, - alreadyCalled = false, - path = require('path'), - makeRequire, stringRequire; - - /** - * Trims the . and .. from an array of path segments. - * It will keep a leading path segment if a .. will become - * the first path segment, to help with module name lookups, - * which act like paths, but can be remapped. But the end result, - * all paths that use this function should look normalized. - * NOTE: this method MODIFIES the input array. - * @param {Array} ary the array of path segments. - */ - function trimDots(ary) { - var i, part; - for (i = 0; ary[i]; i+= 1) { - part = ary[i]; - if (part === '.') { - ary.splice(i, 1); - i -= 1; - } else if (part === '..') { - if (i === 1 && (ary[2] === '..' || ary[0] === '..')) { - //End of the line. Keep at least one non-dot - //path segment at the front so it can be mapped - //correctly to disk. Otherwise, there is likely - //no path mapping for a path starting with '..'. - //This can still fail, but catches the most reasonable - //uses of .. - break; - } else if (i > 0) { - ary.splice(i - 1, 2); - i -= 2; - } - } - } - } - - function normalize(name, baseName) { - var baseParts; - - //Adjust any relative paths. - if (name && name.charAt(0) === '.') { - //If have a base name, try to normalize against it, - //otherwise, assume it is a top-level require that will - //be relative to baseUrl in the end. - if (baseName) { - baseParts = baseName.split('/'); - baseParts = baseParts.slice(0, baseParts.length - 1); - baseParts = baseParts.concat(name.split('/')); - trimDots(baseParts); - name = baseParts.join('/'); - } - } - - return name; - } - - /** - * Create the normalize() function passed to a loader plugin's - * normalize method. - */ - function makeNormalize(relName) { - return function (name) { - return normalize(name, relName); - }; - } - - function makeLoad(id) { - function load(value) { - loaderCache[id] = value; - } - - load.fromText = function (id, text) { - //This one is difficult because the text can/probably uses - //define, and any relative paths and requires should be relative - //to that id was it would be found on disk. But this would require - //bootstrapping a module/require fairly deeply from node core. - //Not sure how best to go about that yet. - throw new Error('amdefine does not implement load.fromText'); - }; - - return load; - } - - makeRequire = function (systemRequire, exports, module, relId) { - function amdRequire(deps, callback) { - if (typeof deps === 'string') { - //Synchronous, single module require('') - return stringRequire(systemRequire, exports, module, deps, relId); - } else { - //Array of dependencies with a callback. - - //Convert the dependencies to modules. - deps = deps.map(function (depName) { - return stringRequire(systemRequire, exports, module, depName, relId); - }); - - //Wait for next tick to call back the require call. - process.nextTick(function () { - callback.apply(null, deps); - }); - } - } - - amdRequire.toUrl = function (filePath) { - if (filePath.indexOf('.') === 0) { - return normalize(filePath, path.dirname(module.filename)); - } else { - return filePath; - } - }; - - return amdRequire; - }; - - //Favor explicit value, passed in if the module wants to support Node 0.4. - requireFn = requireFn || function req() { - return module.require.apply(module, arguments); - }; - - function runFactory(id, deps, factory) { - var r, e, m, result; - - if (id) { - e = loaderCache[id] = {}; - m = { - id: id, - uri: __filename, - exports: e - }; - r = makeRequire(requireFn, e, m, id); - } else { - //Only support one define call per file - if (alreadyCalled) { - throw new Error('amdefine with no module ID cannot be called more than once per file.'); - } - alreadyCalled = true; - - //Use the real variables from node - //Use module.exports for exports, since - //the exports in here is amdefine exports. - e = module.exports; - m = module; - r = makeRequire(requireFn, e, m, module.id); - } - - //If there are dependencies, they are strings, so need - //to convert them to dependency values. - if (deps) { - deps = deps.map(function (depName) { - return r(depName); - }); - } - - //Call the factory with the right dependencies. - if (typeof factory === 'function') { - result = factory.apply(m.exports, deps); - } else { - result = factory; - } - - if (result !== undefined) { - m.exports = result; - if (id) { - loaderCache[id] = m.exports; - } - } - } - - stringRequire = function (systemRequire, exports, module, id, relId) { - //Split the ID by a ! so that - var index = id.indexOf('!'), - originalId = id, - prefix, plugin; - - if (index === -1) { - id = normalize(id, relId); - - //Straight module lookup. If it is one of the special dependencies, - //deal with it, otherwise, delegate to node. - if (id === 'require') { - return makeRequire(systemRequire, exports, module, relId); - } else if (id === 'exports') { - return exports; - } else if (id === 'module') { - return module; - } else if (loaderCache.hasOwnProperty(id)) { - return loaderCache[id]; - } else if (defineCache[id]) { - runFactory.apply(null, defineCache[id]); - return loaderCache[id]; - } else { - if(systemRequire) { - return systemRequire(originalId); - } else { - throw new Error('No module with ID: ' + id); - } - } - } else { - //There is a plugin in play. - prefix = id.substring(0, index); - id = id.substring(index + 1, id.length); - - plugin = stringRequire(systemRequire, exports, module, prefix, relId); - - if (plugin.normalize) { - id = plugin.normalize(id, makeNormalize(relId)); - } else { - //Normalize the ID normally. - id = normalize(id, relId); - } - - if (loaderCache[id]) { - return loaderCache[id]; - } else { - plugin.load(id, makeRequire(systemRequire, exports, module, relId), makeLoad(id), {}); - - return loaderCache[id]; - } - } - }; - - //Create a define function specific to the module asking for amdefine. - function define(id, deps, factory) { - if (Array.isArray(id)) { - factory = deps; - deps = id; - id = undefined; - } else if (typeof id !== 'string') { - factory = id; - id = deps = undefined; - } - - if (deps && !Array.isArray(deps)) { - factory = deps; - deps = undefined; - } - - if (!deps) { - deps = ['require', 'exports', 'module']; - } - - //Set up properties for this module. If an ID, then use - //internal cache. If no ID, then use the external variables - //for this node module. - if (id) { - //Put the module in deep freeze until there is a - //require call for it. - defineCache[id] = [id, deps, factory]; - } else { - runFactory(id, deps, factory); - } - } - - //define.require, which has access to all the values in the - //cache. Useful for AMD modules that all have IDs in the file, - //but need to finally export a value to node based on one of those - //IDs. - define.require = function (id) { - if (loaderCache[id]) { - return loaderCache[id]; - } - - if (defineCache[id]) { - runFactory.apply(null, defineCache[id]); - return loaderCache[id]; - } - }; - - define.amd = {}; - - return define; -} - -module.exports = amdefine; diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/intercept.js b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/intercept.js deleted file mode 100644 index 771a983..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/intercept.js +++ /dev/null @@ -1,36 +0,0 @@ -/*jshint node: true */ -var inserted, - Module = require('module'), - fs = require('fs'), - existingExtFn = Module._extensions['.js'], - amdefineRegExp = /amdefine\.js/; - -inserted = "if (typeof define !== 'function') {var define = require('amdefine')(module)}"; - -//From the node/lib/module.js source: -function stripBOM(content) { - // Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) - // because the buffer-to-string conversion in `fs.readFileSync()` - // translates it to FEFF, the UTF-16 BOM. - if (content.charCodeAt(0) === 0xFEFF) { - content = content.slice(1); - } - return content; -} - -//Also adapted from the node/lib/module.js source: -function intercept(module, filename) { - var content = stripBOM(fs.readFileSync(filename, 'utf8')); - - if (!amdefineRegExp.test(module.id)) { - content = inserted + content; - } - - module._compile(content, filename); -} - -intercept._id = 'amdefine/intercept'; - -if (!existingExtFn._id || existingExtFn._id !== intercept._id) { - Module._extensions['.js'] = intercept; -} diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/package.json b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/package.json deleted file mode 100644 index 7e12668..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "amdefine", - "description": "Provide AMD's define() API for declaring modules in the AMD format", - "version": "0.1.0", - "homepage": "http://github.com/jrburke/amdefine", - "author": { - "name": "James Burke", - "email": "jrburke@gmail.com", - "url": "http://github.com/jrburke" - }, - "licenses": [ - { - "type": "BSD", - "url": "https://github.com/jrburke/amdefine/blob/master/LICENSE" - }, - { - "type": "MIT", - "url": "https://github.com/jrburke/amdefine/blob/master/LICENSE" - } - ], - "repository": { - "type": "git", - "url": "git+https://github.com/jrburke/amdefine.git" - }, - "main": "./amdefine.js", - "engines": { - "node": ">=0.4.2" - }, - "readme": "# amdefine\n\nA module that can be used to implement AMD's define() in Node. This allows you\nto code to the AMD API and have the module work in node programs without\nrequiring those other programs to use AMD.\n\n## Usage\n\n**1)** Update your package.json to indicate amdefine as a dependency:\n\n```javascript\n \"dependencies\": {\n \"amdefine\": \">=0.1.0\"\n }\n```\n\nThen run `npm install` to get amdefine into your project.\n\n**2)** At the top of each module that uses define(), place this code:\n\n```javascript\nif (typeof define !== 'function') { var define = require('amdefine')(module) }\n```\n\n**Only use these snippets** when loading amdefine. If you preserve the basic structure,\nwith the braces, it will be stripped out when using the [RequireJS optimizer](#optimizer).\n\nYou can add spaces, line breaks and even require amdefine with a local path, but\nkeep the rest of the structure to get the stripping behavior.\n\nAs you may know, because `if` statements in JavaScript don't have their own scope, the var\ndeclaration in the above snippet is made whether the `if` expression is truthy or not. If\nRequireJS is loaded then the declaration is superfluous because `define` is already already\ndeclared in the same scope in RequireJS. Fortunately JavaScript handles multiple `var`\ndeclarations of the same variable in the same scope gracefully.\n\nIf you want to deliver amdefine.js with your code rather than specifying it as a dependency\nwith npm, then just download the latest release and refer to it using a relative path:\n\n[Latest Version](https://github.com/jrburke/amdefine/raw/latest/amdefine.js)\n\n### amdefine/intercept\n\nConsider this very experimental.\n\nInstead of pasting the piece of text for the amdefine setup of a `define`\nvariable in each module you create or consume, you can use `amdefine/intercept`\ninstead. It will automatically insert the above snippet in each .js file loaded\nby Node.\n\n**Warning**: you should only use this if you are creating an application that\nis consuming AMD style defined()'d modules that are distributed via npm and want\nto run that code in Node.\n\nFor library code where you are not sure if it will be used by others in Node or\nin the browser, then explicitly depending on amdefine and placing the code\nsnippet above is suggested path, instead of using `amdefine/intercept`. The\nintercept module affects all .js files loaded in the Node app, and it is\ninconsiderate to modify global state like that unless you are also controlling\nthe top level app.\n\n#### Why distribute AMD-style nodes via npm?\n\nnpm has a lot of weaknesses for front-end use (installed layout is not great,\nshould have better support for the `baseUrl + moduleID + '.js' style of loading,\nsingle file JS installs), but some people want a JS package manager and are\nwilling to live with those constraints. If that is you, but still want to author\nin AMD style modules to get dynamic require([]), better direct source usage and\npowerful loader plugin support in the browser, then this tool can help.\n\n#### amdefine/intercept usage\n\nJust require it in your top level app module (for example index.js, server.js):\n\n```javascript\nrequire('amdefine/intercept');\n```\n\nThe module does not return a value, so no need to assign the result to a local\nvariable.\n\nThen just require() code as you normally would with Node's require(). Any .js\nloaded after the intercept require will have the amdefine check injected in\nthe .js source as it is loaded. It does not modify the source on disk, just\nprepends some content to the text of the module as it is loaded by Node.\n\n#### How amdefine/intercept works\n\nIt overrides the `Module._extensions['.js']` in Node to automatically prepend\nthe amdefine snippet above. So, it will affect any .js file loaded by your\napp.\n\n## define() usage\n\nIt is best if you use the anonymous forms of define() in your module:\n\n```javascript\ndefine(function (require) {\n var dependency = require('dependency');\n});\n```\n\nor\n\n```javascript\ndefine(['dependency'], function (dependency) {\n\n});\n```\n\n## RequireJS optimizer integration. \n\nVersion 1.0.3 of the [RequireJS optimizer](http://requirejs.org/docs/optimization.html)\nwill have support for stripping the `if (typeof define !== 'function')` check\nmentioned above, so you can include this snippet for code that runs in the\nbrowser, but avoid taking the cost of the if() statement once the code is\noptimized for deployment.\n\n## Node 0.4 Support\n\nIf you want to support Node 0.4, then add `require` as the second parameter to amdefine:\n\n```javascript\n//Only if you want Node 0.4. If using 0.5 or later, use the above snippet.\nif (typeof define !== 'function') { var define = require('amdefine')(module, require) }\n```\n\n## Limitations\n\n### Synchronous vs Asynchronous\n\namdefine creates a define() function that is callable by your code. It will\nexecute and trace dependencies and call the factory function *synchronously*,\nto keep the behavior in line with Node's synchronous dependency tracing.\n\nThe exception: calling AMD's callback-style require() from inside a factory\nfunction. The require callback is called on process.nextTick():\n\n```javascript\ndefine(function (require) {\n require(['a'], function(a) {\n //'a' is loaded synchronously, but\n //this callback is called on process.nextTick().\n });\n});\n```\n\n### Loader Plugins\n\nLoader plugins are supported as long as they call their load() callbacks\nsynchronously. So ones that do network requests will not work. However plugins\nlike [text](http://requirejs.org/docs/api.html#text) can load text files locally.\n\nThe plugin API's `load.fromText()` is **not supported** in amdefine, so this means\ntranspiler plugins like the [CoffeeScript loader plugin](https://github.com/jrburke/require-cs)\nwill not work. This may be fixable, but it is a bit complex, and I do not have\nenough node-fu to figure it out yet. See the source for amdefine.js if you want\nto get an idea of the issues involved.\n\n## Tests\n\nTo run the tests, cd to **tests** and run:\n\n```\nnode all.js\nnode all-intercept.js\n```\n\n## License\n\nNew BSD and MIT. Check the LICENSE file for all the details.\n", - "readmeFilename": "README.md", - "bugs": { - "url": "https://github.com/jrburke/amdefine/issues" - }, - "_id": "amdefine@0.1.0", - "_from": "amdefine@>=0.0.4", - "scripts": {} -} diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/package.json b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/package.json deleted file mode 100644 index 1f89f50..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/package.json +++ /dev/null @@ -1,186 +0,0 @@ -{ - "name": "source-map", - "description": "Generates and consumes source maps", - "version": "0.1.43", - "homepage": "https://github.com/mozilla/source-map", - "author": { - "name": "Nick Fitzgerald", - "email": "nfitzgerald@mozilla.com" - }, - "contributors": [ - { - "name": "Tobias Koppers", - "email": "tobias.koppers@googlemail.com" - }, - { - "name": "Duncan Beevers", - "email": "duncan@dweebd.com" - }, - { - "name": "Stephen Crane", - "email": "scrane@mozilla.com" - }, - { - "name": "Ryan Seddon", - "email": "seddon.ryan@gmail.com" - }, - { - "name": "Miles Elam", - "email": "miles.elam@deem.com" - }, - { - "name": "Mihai Bazon", - "email": "mihai.bazon@gmail.com" - }, - { - "name": "Michael Ficarra", - "email": "github.public.email@michael.ficarra.me" - }, - { - "name": "Todd Wolfson", - "email": "todd@twolfson.com" - }, - { - "name": "Alexander Solovyov", - "email": "alexander@solovyov.net" - }, - { - "name": "Felix Gnass", - "email": "fgnass@gmail.com" - }, - { - "name": "Conrad Irwin", - "email": "conrad.irwin@gmail.com" - }, - { - "name": "usrbincc", - "email": "usrbincc@yahoo.com" - }, - { - "name": "David Glasser", - "email": "glasser@davidglasser.net" - }, - { - "name": "Chase Douglas", - "email": "chase@newrelic.com" - }, - { - "name": "Evan Wallace", - "email": "evan.exe@gmail.com" - }, - { - "name": "Heather Arthur", - "email": "fayearthur@gmail.com" - }, - { - "name": "Hugh Kennedy", - "email": "hughskennedy@gmail.com" - }, - { - "name": "David Glasser", - "email": "glasser@davidglasser.net" - }, - { - "name": "Simon Lydell", - "email": "simon.lydell@gmail.com" - }, - { - "name": "Jmeas Smith", - "email": "jellyes2@gmail.com" - }, - { - "name": "Michael Z Goddard", - "email": "mzgoddard@gmail.com" - }, - { - "name": "azu", - "email": "azu@users.noreply.github.com" - }, - { - "name": "John Gozde", - "email": "john@gozde.ca" - }, - { - "name": "Adam Kirkton", - "email": "akirkton@truefitinnovation.com" - }, - { - "name": "Chris Montgomery", - "email": "christopher.montgomery@dowjones.com" - }, - { - "name": "J. Ryan Stinnett", - "email": "jryans@gmail.com" - }, - { - "name": "Jack Herrington", - "email": "jherrington@walmartlabs.com" - }, - { - "name": "Chris Truter", - "email": "jeffpalentine@gmail.com" - }, - { - "name": "Daniel Espeset", - "email": "daniel@danielespeset.com" - } - ], - "repository": { - "type": "git", - "url": "git+ssh://git@github.com/mozilla/source-map.git" - }, - "directories": { - "lib": "./lib" - }, - "main": "./lib/source-map.js", - "engines": { - "node": ">=0.8.0" - }, - "licenses": [ - { - "type": "BSD", - "url": "http://opensource.org/licenses/BSD-3-Clause" - } - ], - "dependencies": { - "amdefine": ">=0.0.4" - }, - "devDependencies": { - "dryice": ">=0.4.8" - }, - "scripts": { - "test": "node test/run-tests.js", - "build": "node Makefile.dryice.js" - }, - "bugs": { - "url": "https://github.com/mozilla/source-map/issues" - }, - "_id": "source-map@0.1.43", - "_shasum": "c24bc146ca517c1471f5dacbe2571b2b7f9e3346", - "_from": "source-map@>=0.1.7 <0.2.0", - "_npmVersion": "1.4.9", - "_npmUser": { - "name": "nickfitzgerald", - "email": "fitzgen@gmail.com" - }, - "maintainers": [ - { - "name": "mozilla-devtools", - "email": "mozilla-developer-tools@googlegroups.com" - }, - { - "name": "mozilla", - "email": "dherman@mozilla.com" - }, - { - "name": "nickfitzgerald", - "email": "fitzgen@gmail.com" - } - ], - "dist": { - "shasum": "c24bc146ca517c1471f5dacbe2571b2b7f9e3346", - "tarball": "http://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz" - }, - "_resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "readme": "ERROR: No README data found!" -} diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/run-tests.js b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/run-tests.js deleted file mode 100755 index 64a7c3a..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/run-tests.js +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env node -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ -var assert = require('assert'); -var fs = require('fs'); -var path = require('path'); -var util = require('./source-map/util'); - -function run(tests) { - var total = 0; - var passed = 0; - - for (var i = 0; i < tests.length; i++) { - for (var k in tests[i].testCase) { - if (/^test/.test(k)) { - total++; - try { - tests[i].testCase[k](assert, util); - passed++; - } - catch (e) { - console.log('FAILED ' + tests[i].name + ': ' + k + '!'); - console.log(e.stack); - } - } - } - } - - console.log(''); - console.log(passed + ' / ' + total + ' tests passed.'); - console.log(''); - - return total - passed; -} - -function isTestFile(f) { - var testToRun = process.argv[2]; - return testToRun - ? path.basename(testToRun) === f - : /^test\-.*?\.js/.test(f); -} - -function toModule(f) { - return './source-map/' + f.replace(/\.js$/, ''); -} - -var requires = fs.readdirSync(path.join(__dirname, 'source-map')) - .filter(isTestFile) - .map(toModule); - -var code = run(requires.map(require).map(function (mod, i) { - return { - name: requires[i], - testCase: mod - }; -})); - -process.exit(code); diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-api.js b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-api.js deleted file mode 100644 index 3801233..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-api.js +++ /dev/null @@ -1,26 +0,0 @@ -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2012 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { - - var sourceMap; - try { - sourceMap = require('../../lib/source-map'); - } catch (e) { - sourceMap = {}; - Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap); - } - - exports['test that the api is properly exposed in the top level'] = function (assert, util) { - assert.equal(typeof sourceMap.SourceMapGenerator, "function"); - assert.equal(typeof sourceMap.SourceMapConsumer, "function"); - assert.equal(typeof sourceMap.SourceNode, "function"); - }; - -}); diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-array-set.js b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-array-set.js deleted file mode 100644 index b5797ed..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-array-set.js +++ /dev/null @@ -1,104 +0,0 @@ -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { - - var ArraySet = require('../../lib/source-map/array-set').ArraySet; - - function makeTestSet() { - var set = new ArraySet(); - for (var i = 0; i < 100; i++) { - set.add(String(i)); - } - return set; - } - - exports['test .has() membership'] = function (assert, util) { - var set = makeTestSet(); - for (var i = 0; i < 100; i++) { - assert.ok(set.has(String(i))); - } - }; - - exports['test .indexOf() elements'] = function (assert, util) { - var set = makeTestSet(); - for (var i = 0; i < 100; i++) { - assert.strictEqual(set.indexOf(String(i)), i); - } - }; - - exports['test .at() indexing'] = function (assert, util) { - var set = makeTestSet(); - for (var i = 0; i < 100; i++) { - assert.strictEqual(set.at(i), String(i)); - } - }; - - exports['test creating from an array'] = function (assert, util) { - var set = ArraySet.fromArray(['foo', 'bar', 'baz', 'quux', 'hasOwnProperty']); - - assert.ok(set.has('foo')); - assert.ok(set.has('bar')); - assert.ok(set.has('baz')); - assert.ok(set.has('quux')); - assert.ok(set.has('hasOwnProperty')); - - assert.strictEqual(set.indexOf('foo'), 0); - assert.strictEqual(set.indexOf('bar'), 1); - assert.strictEqual(set.indexOf('baz'), 2); - assert.strictEqual(set.indexOf('quux'), 3); - - assert.strictEqual(set.at(0), 'foo'); - assert.strictEqual(set.at(1), 'bar'); - assert.strictEqual(set.at(2), 'baz'); - assert.strictEqual(set.at(3), 'quux'); - }; - - exports['test that you can add __proto__; see github issue #30'] = function (assert, util) { - var set = new ArraySet(); - set.add('__proto__'); - assert.ok(set.has('__proto__')); - assert.strictEqual(set.at(0), '__proto__'); - assert.strictEqual(set.indexOf('__proto__'), 0); - }; - - exports['test .fromArray() with duplicates'] = function (assert, util) { - var set = ArraySet.fromArray(['foo', 'foo']); - assert.ok(set.has('foo')); - assert.strictEqual(set.at(0), 'foo'); - assert.strictEqual(set.indexOf('foo'), 0); - assert.strictEqual(set.toArray().length, 1); - - set = ArraySet.fromArray(['foo', 'foo'], true); - assert.ok(set.has('foo')); - assert.strictEqual(set.at(0), 'foo'); - assert.strictEqual(set.at(1), 'foo'); - assert.strictEqual(set.indexOf('foo'), 0); - assert.strictEqual(set.toArray().length, 2); - }; - - exports['test .add() with duplicates'] = function (assert, util) { - var set = new ArraySet(); - set.add('foo'); - - set.add('foo'); - assert.ok(set.has('foo')); - assert.strictEqual(set.at(0), 'foo'); - assert.strictEqual(set.indexOf('foo'), 0); - assert.strictEqual(set.toArray().length, 1); - - set.add('foo', true); - assert.ok(set.has('foo')); - assert.strictEqual(set.at(0), 'foo'); - assert.strictEqual(set.at(1), 'foo'); - assert.strictEqual(set.indexOf('foo'), 0); - assert.strictEqual(set.toArray().length, 2); - }; - -}); diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64-vlq.js b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64-vlq.js deleted file mode 100644 index 6fd0d99..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64-vlq.js +++ /dev/null @@ -1,23 +0,0 @@ -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { - - var base64VLQ = require('../../lib/source-map/base64-vlq'); - - exports['test normal encoding and decoding'] = function (assert, util) { - var result = {}; - for (var i = -255; i < 256; i++) { - base64VLQ.decode(base64VLQ.encode(i), result); - assert.equal(result.value, i); - assert.equal(result.rest, ""); - } - }; - -}); diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64.js b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64.js deleted file mode 100644 index ff3a244..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64.js +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { - - var base64 = require('../../lib/source-map/base64'); - - exports['test out of range encoding'] = function (assert, util) { - assert.throws(function () { - base64.encode(-1); - }); - assert.throws(function () { - base64.encode(64); - }); - }; - - exports['test out of range decoding'] = function (assert, util) { - assert.throws(function () { - base64.decode('='); - }); - }; - - exports['test normal encoding and decoding'] = function (assert, util) { - for (var i = 0; i < 64; i++) { - assert.equal(base64.decode(base64.encode(i)), i); - } - }; - -}); diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-binary-search.js b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-binary-search.js deleted file mode 100644 index f1c9e0f..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-binary-search.js +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { - - var binarySearch = require('../../lib/source-map/binary-search'); - - function numberCompare(a, b) { - return a - b; - } - - exports['test too high'] = function (assert, util) { - var needle = 30; - var haystack = [2,4,6,8,10,12,14,16,18,20]; - - assert.doesNotThrow(function () { - binarySearch.search(needle, haystack, numberCompare); - }); - - assert.equal(haystack[binarySearch.search(needle, haystack, numberCompare)], 20); - }; - - exports['test too low'] = function (assert, util) { - var needle = 1; - var haystack = [2,4,6,8,10,12,14,16,18,20]; - - assert.doesNotThrow(function () { - binarySearch.search(needle, haystack, numberCompare); - }); - - assert.equal(binarySearch.search(needle, haystack, numberCompare), -1); - }; - - exports['test exact search'] = function (assert, util) { - var needle = 4; - var haystack = [2,4,6,8,10,12,14,16,18,20]; - - assert.equal(haystack[binarySearch.search(needle, haystack, numberCompare)], 4); - }; - - exports['test fuzzy search'] = function (assert, util) { - var needle = 19; - var haystack = [2,4,6,8,10,12,14,16,18,20]; - - assert.equal(haystack[binarySearch.search(needle, haystack, numberCompare)], 18); - }; - -}); diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-dog-fooding.js b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-dog-fooding.js deleted file mode 100644 index 26757b2..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-dog-fooding.js +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { - - var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; - var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; - - exports['test eating our own dog food'] = function (assert, util) { - var smg = new SourceMapGenerator({ - file: 'testing.js', - sourceRoot: '/wu/tang' - }); - - smg.addMapping({ - source: 'gza.coffee', - original: { line: 1, column: 0 }, - generated: { line: 2, column: 2 } - }); - - smg.addMapping({ - source: 'gza.coffee', - original: { line: 2, column: 0 }, - generated: { line: 3, column: 2 } - }); - - smg.addMapping({ - source: 'gza.coffee', - original: { line: 3, column: 0 }, - generated: { line: 4, column: 2 } - }); - - smg.addMapping({ - source: 'gza.coffee', - original: { line: 4, column: 0 }, - generated: { line: 5, column: 2 } - }); - - smg.addMapping({ - source: 'gza.coffee', - original: { line: 5, column: 10 }, - generated: { line: 6, column: 12 } - }); - - var smc = new SourceMapConsumer(smg.toString()); - - // Exact - util.assertMapping(2, 2, '/wu/tang/gza.coffee', 1, 0, null, smc, assert); - util.assertMapping(3, 2, '/wu/tang/gza.coffee', 2, 0, null, smc, assert); - util.assertMapping(4, 2, '/wu/tang/gza.coffee', 3, 0, null, smc, assert); - util.assertMapping(5, 2, '/wu/tang/gza.coffee', 4, 0, null, smc, assert); - util.assertMapping(6, 12, '/wu/tang/gza.coffee', 5, 10, null, smc, assert); - - // Fuzzy - - // Generated to original - util.assertMapping(2, 0, null, null, null, null, smc, assert, true); - util.assertMapping(2, 9, '/wu/tang/gza.coffee', 1, 0, null, smc, assert, true); - util.assertMapping(3, 0, null, null, null, null, smc, assert, true); - util.assertMapping(3, 9, '/wu/tang/gza.coffee', 2, 0, null, smc, assert, true); - util.assertMapping(4, 0, null, null, null, null, smc, assert, true); - util.assertMapping(4, 9, '/wu/tang/gza.coffee', 3, 0, null, smc, assert, true); - util.assertMapping(5, 0, null, null, null, null, smc, assert, true); - util.assertMapping(5, 9, '/wu/tang/gza.coffee', 4, 0, null, smc, assert, true); - util.assertMapping(6, 0, null, null, null, null, smc, assert, true); - util.assertMapping(6, 9, null, null, null, null, smc, assert, true); - util.assertMapping(6, 13, '/wu/tang/gza.coffee', 5, 10, null, smc, assert, true); - - // Original to generated - util.assertMapping(2, 2, '/wu/tang/gza.coffee', 1, 1, null, smc, assert, null, true); - util.assertMapping(3, 2, '/wu/tang/gza.coffee', 2, 3, null, smc, assert, null, true); - util.assertMapping(4, 2, '/wu/tang/gza.coffee', 3, 6, null, smc, assert, null, true); - util.assertMapping(5, 2, '/wu/tang/gza.coffee', 4, 9, null, smc, assert, null, true); - util.assertMapping(5, 2, '/wu/tang/gza.coffee', 5, 9, null, smc, assert, null, true); - util.assertMapping(6, 12, '/wu/tang/gza.coffee', 6, 19, null, smc, assert, null, true); - }; - -}); diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-consumer.js b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-consumer.js deleted file mode 100644 index c714943..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-consumer.js +++ /dev/null @@ -1,702 +0,0 @@ -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { - - var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; - var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; - - exports['test that we can instantiate with a string or an object'] = function (assert, util) { - assert.doesNotThrow(function () { - var map = new SourceMapConsumer(util.testMap); - }); - assert.doesNotThrow(function () { - var map = new SourceMapConsumer(JSON.stringify(util.testMap)); - }); - }; - - exports['test that the `sources` field has the original sources'] = function (assert, util) { - var map; - var sources; - - map = new SourceMapConsumer(util.testMap); - sources = map.sources; - assert.equal(sources[0], '/the/root/one.js'); - assert.equal(sources[1], '/the/root/two.js'); - assert.equal(sources.length, 2); - - map = new SourceMapConsumer(util.testMapNoSourceRoot); - sources = map.sources; - assert.equal(sources[0], 'one.js'); - assert.equal(sources[1], 'two.js'); - assert.equal(sources.length, 2); - - map = new SourceMapConsumer(util.testMapEmptySourceRoot); - sources = map.sources; - assert.equal(sources[0], 'one.js'); - assert.equal(sources[1], 'two.js'); - assert.equal(sources.length, 2); - }; - - exports['test that the source root is reflected in a mapping\'s source field'] = function (assert, util) { - var map; - var mapping; - - map = new SourceMapConsumer(util.testMap); - - mapping = map.originalPositionFor({ - line: 2, - column: 1 - }); - assert.equal(mapping.source, '/the/root/two.js'); - - mapping = map.originalPositionFor({ - line: 1, - column: 1 - }); - assert.equal(mapping.source, '/the/root/one.js'); - - - map = new SourceMapConsumer(util.testMapNoSourceRoot); - - mapping = map.originalPositionFor({ - line: 2, - column: 1 - }); - assert.equal(mapping.source, 'two.js'); - - mapping = map.originalPositionFor({ - line: 1, - column: 1 - }); - assert.equal(mapping.source, 'one.js'); - - - map = new SourceMapConsumer(util.testMapEmptySourceRoot); - - mapping = map.originalPositionFor({ - line: 2, - column: 1 - }); - assert.equal(mapping.source, 'two.js'); - - mapping = map.originalPositionFor({ - line: 1, - column: 1 - }); - assert.equal(mapping.source, 'one.js'); - }; - - exports['test mapping tokens back exactly'] = function (assert, util) { - var map = new SourceMapConsumer(util.testMap); - - util.assertMapping(1, 1, '/the/root/one.js', 1, 1, null, map, assert); - util.assertMapping(1, 5, '/the/root/one.js', 1, 5, null, map, assert); - util.assertMapping(1, 9, '/the/root/one.js', 1, 11, null, map, assert); - util.assertMapping(1, 18, '/the/root/one.js', 1, 21, 'bar', map, assert); - util.assertMapping(1, 21, '/the/root/one.js', 2, 3, null, map, assert); - util.assertMapping(1, 28, '/the/root/one.js', 2, 10, 'baz', map, assert); - util.assertMapping(1, 32, '/the/root/one.js', 2, 14, 'bar', map, assert); - - util.assertMapping(2, 1, '/the/root/two.js', 1, 1, null, map, assert); - util.assertMapping(2, 5, '/the/root/two.js', 1, 5, null, map, assert); - util.assertMapping(2, 9, '/the/root/two.js', 1, 11, null, map, assert); - util.assertMapping(2, 18, '/the/root/two.js', 1, 21, 'n', map, assert); - util.assertMapping(2, 21, '/the/root/two.js', 2, 3, null, map, assert); - util.assertMapping(2, 28, '/the/root/two.js', 2, 10, 'n', map, assert); - }; - - exports['test mapping tokens fuzzy'] = function (assert, util) { - var map = new SourceMapConsumer(util.testMap); - - // Finding original positions - util.assertMapping(1, 20, '/the/root/one.js', 1, 21, 'bar', map, assert, true); - util.assertMapping(1, 30, '/the/root/one.js', 2, 10, 'baz', map, assert, true); - util.assertMapping(2, 12, '/the/root/two.js', 1, 11, null, map, assert, true); - - // Finding generated positions - util.assertMapping(1, 18, '/the/root/one.js', 1, 22, 'bar', map, assert, null, true); - util.assertMapping(1, 28, '/the/root/one.js', 2, 13, 'baz', map, assert, null, true); - util.assertMapping(2, 9, '/the/root/two.js', 1, 16, null, map, assert, null, true); - }; - - exports['test mappings and end of lines'] = function (assert, util) { - var smg = new SourceMapGenerator({ - file: 'foo.js' - }); - smg.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 1, column: 1 }, - source: 'bar.js' - }); - smg.addMapping({ - original: { line: 2, column: 2 }, - generated: { line: 2, column: 2 }, - source: 'bar.js' - }); - - var map = SourceMapConsumer.fromSourceMap(smg); - - // When finding original positions, mappings end at the end of the line. - util.assertMapping(2, 1, null, null, null, null, map, assert, true) - - // When finding generated positions, mappings do not end at the end of the line. - util.assertMapping(1, 1, 'bar.js', 2, 1, null, map, assert, null, true); - }; - - exports['test creating source map consumers with )]}\' prefix'] = function (assert, util) { - assert.doesNotThrow(function () { - var map = new SourceMapConsumer(")]}'" + JSON.stringify(util.testMap)); - }); - }; - - exports['test eachMapping'] = function (assert, util) { - var map; - - map = new SourceMapConsumer(util.testMap); - var previousLine = -Infinity; - var previousColumn = -Infinity; - map.eachMapping(function (mapping) { - assert.ok(mapping.generatedLine >= previousLine); - - assert.ok(mapping.source === '/the/root/one.js' || mapping.source === '/the/root/two.js'); - - if (mapping.generatedLine === previousLine) { - assert.ok(mapping.generatedColumn >= previousColumn); - previousColumn = mapping.generatedColumn; - } - else { - previousLine = mapping.generatedLine; - previousColumn = -Infinity; - } - }); - - map = new SourceMapConsumer(util.testMapNoSourceRoot); - map.eachMapping(function (mapping) { - assert.ok(mapping.source === 'one.js' || mapping.source === 'two.js'); - }); - - map = new SourceMapConsumer(util.testMapEmptySourceRoot); - map.eachMapping(function (mapping) { - assert.ok(mapping.source === 'one.js' || mapping.source === 'two.js'); - }); - }; - - exports['test iterating over mappings in a different order'] = function (assert, util) { - var map = new SourceMapConsumer(util.testMap); - var previousLine = -Infinity; - var previousColumn = -Infinity; - var previousSource = ""; - map.eachMapping(function (mapping) { - assert.ok(mapping.source >= previousSource); - - if (mapping.source === previousSource) { - assert.ok(mapping.originalLine >= previousLine); - - if (mapping.originalLine === previousLine) { - assert.ok(mapping.originalColumn >= previousColumn); - previousColumn = mapping.originalColumn; - } - else { - previousLine = mapping.originalLine; - previousColumn = -Infinity; - } - } - else { - previousSource = mapping.source; - previousLine = -Infinity; - previousColumn = -Infinity; - } - }, null, SourceMapConsumer.ORIGINAL_ORDER); - }; - - exports['test that we can set the context for `this` in eachMapping'] = function (assert, util) { - var map = new SourceMapConsumer(util.testMap); - var context = {}; - map.eachMapping(function () { - assert.equal(this, context); - }, context); - }; - - exports['test that the `sourcesContent` field has the original sources'] = function (assert, util) { - var map = new SourceMapConsumer(util.testMapWithSourcesContent); - var sourcesContent = map.sourcesContent; - - assert.equal(sourcesContent[0], ' ONE.foo = function (bar) {\n return baz(bar);\n };'); - assert.equal(sourcesContent[1], ' TWO.inc = function (n) {\n return n + 1;\n };'); - assert.equal(sourcesContent.length, 2); - }; - - exports['test that we can get the original sources for the sources'] = function (assert, util) { - var map = new SourceMapConsumer(util.testMapWithSourcesContent); - var sources = map.sources; - - assert.equal(map.sourceContentFor(sources[0]), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); - assert.equal(map.sourceContentFor(sources[1]), ' TWO.inc = function (n) {\n return n + 1;\n };'); - assert.equal(map.sourceContentFor("one.js"), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); - assert.equal(map.sourceContentFor("two.js"), ' TWO.inc = function (n) {\n return n + 1;\n };'); - assert.throws(function () { - map.sourceContentFor(""); - }, Error); - assert.throws(function () { - map.sourceContentFor("/the/root/three.js"); - }, Error); - assert.throws(function () { - map.sourceContentFor("three.js"); - }, Error); - }; - - exports['test that we can get the original source content with relative source paths'] = function (assert, util) { - var map = new SourceMapConsumer(util.testMapRelativeSources); - var sources = map.sources; - - assert.equal(map.sourceContentFor(sources[0]), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); - assert.equal(map.sourceContentFor(sources[1]), ' TWO.inc = function (n) {\n return n + 1;\n };'); - assert.equal(map.sourceContentFor("one.js"), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); - assert.equal(map.sourceContentFor("two.js"), ' TWO.inc = function (n) {\n return n + 1;\n };'); - assert.throws(function () { - map.sourceContentFor(""); - }, Error); - assert.throws(function () { - map.sourceContentFor("/the/root/three.js"); - }, Error); - assert.throws(function () { - map.sourceContentFor("three.js"); - }, Error); - }; - - exports['test sourceRoot + generatedPositionFor'] = function (assert, util) { - var map = new SourceMapGenerator({ - sourceRoot: 'foo/bar', - file: 'baz.js' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 2, column: 2 }, - source: 'bang.coffee' - }); - map.addMapping({ - original: { line: 5, column: 5 }, - generated: { line: 6, column: 6 }, - source: 'bang.coffee' - }); - map = new SourceMapConsumer(map.toString()); - - // Should handle without sourceRoot. - var pos = map.generatedPositionFor({ - line: 1, - column: 1, - source: 'bang.coffee' - }); - - assert.equal(pos.line, 2); - assert.equal(pos.column, 2); - - // Should handle with sourceRoot. - var pos = map.generatedPositionFor({ - line: 1, - column: 1, - source: 'foo/bar/bang.coffee' - }); - - assert.equal(pos.line, 2); - assert.equal(pos.column, 2); - }; - - exports['test allGeneratedPositionsFor'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'generated.js' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 2, column: 2 }, - source: 'foo.coffee' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 2, column: 2 }, - source: 'bar.coffee' - }); - map.addMapping({ - original: { line: 2, column: 1 }, - generated: { line: 3, column: 2 }, - source: 'bar.coffee' - }); - map.addMapping({ - original: { line: 2, column: 2 }, - generated: { line: 3, column: 3 }, - source: 'bar.coffee' - }); - map.addMapping({ - original: { line: 3, column: 1 }, - generated: { line: 4, column: 2 }, - source: 'bar.coffee' - }); - map = new SourceMapConsumer(map.toString()); - - var mappings = map.allGeneratedPositionsFor({ - line: 2, - source: 'bar.coffee' - }); - - assert.equal(mappings.length, 2); - assert.equal(mappings[0].line, 3); - assert.equal(mappings[0].column, 2); - assert.equal(mappings[1].line, 3); - assert.equal(mappings[1].column, 3); - }; - - exports['test allGeneratedPositionsFor for line with no mappings'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'generated.js' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 2, column: 2 }, - source: 'foo.coffee' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 2, column: 2 }, - source: 'bar.coffee' - }); - map.addMapping({ - original: { line: 3, column: 1 }, - generated: { line: 4, column: 2 }, - source: 'bar.coffee' - }); - map = new SourceMapConsumer(map.toString()); - - var mappings = map.allGeneratedPositionsFor({ - line: 2, - source: 'bar.coffee' - }); - - assert.equal(mappings.length, 0); - }; - - exports['test allGeneratedPositionsFor source map with no mappings'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'generated.js' - }); - map = new SourceMapConsumer(map.toString()); - - var mappings = map.allGeneratedPositionsFor({ - line: 2, - source: 'bar.coffee' - }); - - assert.equal(mappings.length, 0); - }; - - exports['test computeColumnSpans'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'generated.js' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 1, column: 1 }, - source: 'foo.coffee' - }); - map.addMapping({ - original: { line: 2, column: 1 }, - generated: { line: 2, column: 1 }, - source: 'foo.coffee' - }); - map.addMapping({ - original: { line: 2, column: 2 }, - generated: { line: 2, column: 10 }, - source: 'foo.coffee' - }); - map.addMapping({ - original: { line: 2, column: 3 }, - generated: { line: 2, column: 20 }, - source: 'foo.coffee' - }); - map.addMapping({ - original: { line: 3, column: 1 }, - generated: { line: 3, column: 1 }, - source: 'foo.coffee' - }); - map.addMapping({ - original: { line: 3, column: 2 }, - generated: { line: 3, column: 2 }, - source: 'foo.coffee' - }); - map = new SourceMapConsumer(map.toString()); - - map.computeColumnSpans(); - - var mappings = map.allGeneratedPositionsFor({ - line: 1, - source: 'foo.coffee' - }); - - assert.equal(mappings.length, 1); - assert.equal(mappings[0].lastColumn, Infinity); - - var mappings = map.allGeneratedPositionsFor({ - line: 2, - source: 'foo.coffee' - }); - - assert.equal(mappings.length, 3); - assert.equal(mappings[0].lastColumn, 9); - assert.equal(mappings[1].lastColumn, 19); - assert.equal(mappings[2].lastColumn, Infinity); - - var mappings = map.allGeneratedPositionsFor({ - line: 3, - source: 'foo.coffee' - }); - - assert.equal(mappings.length, 2); - assert.equal(mappings[0].lastColumn, 1); - assert.equal(mappings[1].lastColumn, Infinity); - }; - - exports['test sourceRoot + originalPositionFor'] = function (assert, util) { - var map = new SourceMapGenerator({ - sourceRoot: 'foo/bar', - file: 'baz.js' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 2, column: 2 }, - source: 'bang.coffee' - }); - map = new SourceMapConsumer(map.toString()); - - var pos = map.originalPositionFor({ - line: 2, - column: 2, - }); - - // Should always have the prepended source root - assert.equal(pos.source, 'foo/bar/bang.coffee'); - assert.equal(pos.line, 1); - assert.equal(pos.column, 1); - }; - - exports['test github issue #56'] = function (assert, util) { - var map = new SourceMapGenerator({ - sourceRoot: 'http://', - file: 'www.example.com/foo.js' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 2, column: 2 }, - source: 'www.example.com/original.js' - }); - map = new SourceMapConsumer(map.toString()); - - var sources = map.sources; - assert.equal(sources.length, 1); - assert.equal(sources[0], 'http://www.example.com/original.js'); - }; - - exports['test github issue #43'] = function (assert, util) { - var map = new SourceMapGenerator({ - sourceRoot: 'http://example.com', - file: 'foo.js' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 2, column: 2 }, - source: 'http://cdn.example.com/original.js' - }); - map = new SourceMapConsumer(map.toString()); - - var sources = map.sources; - assert.equal(sources.length, 1, - 'Should only be one source.'); - assert.equal(sources[0], 'http://cdn.example.com/original.js', - 'Should not be joined with the sourceRoot.'); - }; - - exports['test absolute path, but same host sources'] = function (assert, util) { - var map = new SourceMapGenerator({ - sourceRoot: 'http://example.com/foo/bar', - file: 'foo.js' - }); - map.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 2, column: 2 }, - source: '/original.js' - }); - map = new SourceMapConsumer(map.toString()); - - var sources = map.sources; - assert.equal(sources.length, 1, - 'Should only be one source.'); - assert.equal(sources[0], 'http://example.com/original.js', - 'Source should be relative the host of the source root.'); - }; - - exports['test github issue #64'] = function (assert, util) { - var map = new SourceMapConsumer({ - "version": 3, - "file": "foo.js", - "sourceRoot": "http://example.com/", - "sources": ["/a"], - "names": [], - "mappings": "AACA", - "sourcesContent": ["foo"] - }); - - assert.equal(map.sourceContentFor("a"), "foo"); - assert.equal(map.sourceContentFor("/a"), "foo"); - }; - - exports['test bug 885597'] = function (assert, util) { - var map = new SourceMapConsumer({ - "version": 3, - "file": "foo.js", - "sourceRoot": "file:///Users/AlGore/Invented/The/Internet/", - "sources": ["/a"], - "names": [], - "mappings": "AACA", - "sourcesContent": ["foo"] - }); - - var s = map.sources[0]; - assert.equal(map.sourceContentFor(s), "foo"); - }; - - exports['test github issue #72, duplicate sources'] = function (assert, util) { - var map = new SourceMapConsumer({ - "version": 3, - "file": "foo.js", - "sources": ["source1.js", "source1.js", "source3.js"], - "names": [], - "mappings": ";EAAC;;IAEE;;MEEE", - "sourceRoot": "http://example.com" - }); - - var pos = map.originalPositionFor({ - line: 2, - column: 2 - }); - assert.equal(pos.source, 'http://example.com/source1.js'); - assert.equal(pos.line, 1); - assert.equal(pos.column, 1); - - var pos = map.originalPositionFor({ - line: 4, - column: 4 - }); - assert.equal(pos.source, 'http://example.com/source1.js'); - assert.equal(pos.line, 3); - assert.equal(pos.column, 3); - - var pos = map.originalPositionFor({ - line: 6, - column: 6 - }); - assert.equal(pos.source, 'http://example.com/source3.js'); - assert.equal(pos.line, 5); - assert.equal(pos.column, 5); - }; - - exports['test github issue #72, duplicate names'] = function (assert, util) { - var map = new SourceMapConsumer({ - "version": 3, - "file": "foo.js", - "sources": ["source.js"], - "names": ["name1", "name1", "name3"], - "mappings": ";EAACA;;IAEEA;;MAEEE", - "sourceRoot": "http://example.com" - }); - - var pos = map.originalPositionFor({ - line: 2, - column: 2 - }); - assert.equal(pos.name, 'name1'); - assert.equal(pos.line, 1); - assert.equal(pos.column, 1); - - var pos = map.originalPositionFor({ - line: 4, - column: 4 - }); - assert.equal(pos.name, 'name1'); - assert.equal(pos.line, 3); - assert.equal(pos.column, 3); - - var pos = map.originalPositionFor({ - line: 6, - column: 6 - }); - assert.equal(pos.name, 'name3'); - assert.equal(pos.line, 5); - assert.equal(pos.column, 5); - }; - - exports['test SourceMapConsumer.fromSourceMap'] = function (assert, util) { - var smg = new SourceMapGenerator({ - sourceRoot: 'http://example.com/', - file: 'foo.js' - }); - smg.addMapping({ - original: { line: 1, column: 1 }, - generated: { line: 2, column: 2 }, - source: 'bar.js' - }); - smg.addMapping({ - original: { line: 2, column: 2 }, - generated: { line: 4, column: 4 }, - source: 'baz.js', - name: 'dirtMcGirt' - }); - smg.setSourceContent('baz.js', 'baz.js content'); - - var smc = SourceMapConsumer.fromSourceMap(smg); - assert.equal(smc.file, 'foo.js'); - assert.equal(smc.sourceRoot, 'http://example.com/'); - assert.equal(smc.sources.length, 2); - assert.equal(smc.sources[0], 'http://example.com/bar.js'); - assert.equal(smc.sources[1], 'http://example.com/baz.js'); - assert.equal(smc.sourceContentFor('baz.js'), 'baz.js content'); - - var pos = smc.originalPositionFor({ - line: 2, - column: 2 - }); - assert.equal(pos.line, 1); - assert.equal(pos.column, 1); - assert.equal(pos.source, 'http://example.com/bar.js'); - assert.equal(pos.name, null); - - pos = smc.generatedPositionFor({ - line: 1, - column: 1, - source: 'http://example.com/bar.js' - }); - assert.equal(pos.line, 2); - assert.equal(pos.column, 2); - - pos = smc.originalPositionFor({ - line: 4, - column: 4 - }); - assert.equal(pos.line, 2); - assert.equal(pos.column, 2); - assert.equal(pos.source, 'http://example.com/baz.js'); - assert.equal(pos.name, 'dirtMcGirt'); - - pos = smc.generatedPositionFor({ - line: 2, - column: 2, - source: 'http://example.com/baz.js' - }); - assert.equal(pos.line, 4); - assert.equal(pos.column, 4); - }; -}); diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-generator.js b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-generator.js deleted file mode 100644 index d748bb1..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-generator.js +++ /dev/null @@ -1,679 +0,0 @@ -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { - - var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; - var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; - var SourceNode = require('../../lib/source-map/source-node').SourceNode; - var util = require('./util'); - - exports['test some simple stuff'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'foo.js', - sourceRoot: '.' - }); - assert.ok(true); - - var map = new SourceMapGenerator().toJSON(); - assert.ok(!('file' in map)); - assert.ok(!('sourceRoot' in map)); - }; - - exports['test JSON serialization'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'foo.js', - sourceRoot: '.' - }); - assert.equal(map.toString(), JSON.stringify(map)); - }; - - exports['test adding mappings (case 1)'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'generated-foo.js', - sourceRoot: '.' - }); - - assert.doesNotThrow(function () { - map.addMapping({ - generated: { line: 1, column: 1 } - }); - }); - }; - - exports['test adding mappings (case 2)'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'generated-foo.js', - sourceRoot: '.' - }); - - assert.doesNotThrow(function () { - map.addMapping({ - generated: { line: 1, column: 1 }, - source: 'bar.js', - original: { line: 1, column: 1 } - }); - }); - }; - - exports['test adding mappings (case 3)'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'generated-foo.js', - sourceRoot: '.' - }); - - assert.doesNotThrow(function () { - map.addMapping({ - generated: { line: 1, column: 1 }, - source: 'bar.js', - original: { line: 1, column: 1 }, - name: 'someToken' - }); - }); - }; - - exports['test adding mappings (invalid)'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'generated-foo.js', - sourceRoot: '.' - }); - - // Not enough info. - assert.throws(function () { - map.addMapping({}); - }); - - // Original file position, but no source. - assert.throws(function () { - map.addMapping({ - generated: { line: 1, column: 1 }, - original: { line: 1, column: 1 } - }); - }); - }; - - exports['test adding mappings with skipValidation'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'generated-foo.js', - sourceRoot: '.', - skipValidation: true - }); - - // Not enough info, caught by `util.getArgs` - assert.throws(function () { - map.addMapping({}); - }); - - // Original file position, but no source. Not checked. - assert.doesNotThrow(function () { - map.addMapping({ - generated: { line: 1, column: 1 }, - original: { line: 1, column: 1 } - }); - }); - }; - - exports['test that the correct mappings are being generated'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'min.js', - sourceRoot: '/the/root' - }); - - map.addMapping({ - generated: { line: 1, column: 1 }, - original: { line: 1, column: 1 }, - source: 'one.js' - }); - map.addMapping({ - generated: { line: 1, column: 5 }, - original: { line: 1, column: 5 }, - source: 'one.js' - }); - map.addMapping({ - generated: { line: 1, column: 9 }, - original: { line: 1, column: 11 }, - source: 'one.js' - }); - map.addMapping({ - generated: { line: 1, column: 18 }, - original: { line: 1, column: 21 }, - source: 'one.js', - name: 'bar' - }); - map.addMapping({ - generated: { line: 1, column: 21 }, - original: { line: 2, column: 3 }, - source: 'one.js' - }); - map.addMapping({ - generated: { line: 1, column: 28 }, - original: { line: 2, column: 10 }, - source: 'one.js', - name: 'baz' - }); - map.addMapping({ - generated: { line: 1, column: 32 }, - original: { line: 2, column: 14 }, - source: 'one.js', - name: 'bar' - }); - - map.addMapping({ - generated: { line: 2, column: 1 }, - original: { line: 1, column: 1 }, - source: 'two.js' - }); - map.addMapping({ - generated: { line: 2, column: 5 }, - original: { line: 1, column: 5 }, - source: 'two.js' - }); - map.addMapping({ - generated: { line: 2, column: 9 }, - original: { line: 1, column: 11 }, - source: 'two.js' - }); - map.addMapping({ - generated: { line: 2, column: 18 }, - original: { line: 1, column: 21 }, - source: 'two.js', - name: 'n' - }); - map.addMapping({ - generated: { line: 2, column: 21 }, - original: { line: 2, column: 3 }, - source: 'two.js' - }); - map.addMapping({ - generated: { line: 2, column: 28 }, - original: { line: 2, column: 10 }, - source: 'two.js', - name: 'n' - }); - - map = JSON.parse(map.toString()); - - util.assertEqualMaps(assert, map, util.testMap); - }; - - exports['test that adding a mapping with an empty string name does not break generation'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'generated-foo.js', - sourceRoot: '.' - }); - - map.addMapping({ - generated: { line: 1, column: 1 }, - source: 'bar.js', - original: { line: 1, column: 1 }, - name: '' - }); - - assert.doesNotThrow(function () { - JSON.parse(map.toString()); - }); - }; - - exports['test that source content can be set'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'min.js', - sourceRoot: '/the/root' - }); - map.addMapping({ - generated: { line: 1, column: 1 }, - original: { line: 1, column: 1 }, - source: 'one.js' - }); - map.addMapping({ - generated: { line: 2, column: 1 }, - original: { line: 1, column: 1 }, - source: 'two.js' - }); - map.setSourceContent('one.js', 'one file content'); - - map = JSON.parse(map.toString()); - assert.equal(map.sources[0], 'one.js'); - assert.equal(map.sources[1], 'two.js'); - assert.equal(map.sourcesContent[0], 'one file content'); - assert.equal(map.sourcesContent[1], null); - }; - - exports['test .fromSourceMap'] = function (assert, util) { - var map = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(util.testMap)); - util.assertEqualMaps(assert, map.toJSON(), util.testMap); - }; - - exports['test .fromSourceMap with sourcesContent'] = function (assert, util) { - var map = SourceMapGenerator.fromSourceMap( - new SourceMapConsumer(util.testMapWithSourcesContent)); - util.assertEqualMaps(assert, map.toJSON(), util.testMapWithSourcesContent); - }; - - exports['test applySourceMap'] = function (assert, util) { - var node = new SourceNode(null, null, null, [ - new SourceNode(2, 0, 'fileX', 'lineX2\n'), - 'genA1\n', - new SourceNode(2, 0, 'fileY', 'lineY2\n'), - 'genA2\n', - new SourceNode(1, 0, 'fileX', 'lineX1\n'), - 'genA3\n', - new SourceNode(1, 0, 'fileY', 'lineY1\n') - ]); - var mapStep1 = node.toStringWithSourceMap({ - file: 'fileA' - }).map; - mapStep1.setSourceContent('fileX', 'lineX1\nlineX2\n'); - mapStep1 = mapStep1.toJSON(); - - node = new SourceNode(null, null, null, [ - 'gen1\n', - new SourceNode(1, 0, 'fileA', 'lineA1\n'), - new SourceNode(2, 0, 'fileA', 'lineA2\n'), - new SourceNode(3, 0, 'fileA', 'lineA3\n'), - new SourceNode(4, 0, 'fileA', 'lineA4\n'), - new SourceNode(1, 0, 'fileB', 'lineB1\n'), - new SourceNode(2, 0, 'fileB', 'lineB2\n'), - 'gen2\n' - ]); - var mapStep2 = node.toStringWithSourceMap({ - file: 'fileGen' - }).map; - mapStep2.setSourceContent('fileB', 'lineB1\nlineB2\n'); - mapStep2 = mapStep2.toJSON(); - - node = new SourceNode(null, null, null, [ - 'gen1\n', - new SourceNode(2, 0, 'fileX', 'lineA1\n'), - new SourceNode(2, 0, 'fileA', 'lineA2\n'), - new SourceNode(2, 0, 'fileY', 'lineA3\n'), - new SourceNode(4, 0, 'fileA', 'lineA4\n'), - new SourceNode(1, 0, 'fileB', 'lineB1\n'), - new SourceNode(2, 0, 'fileB', 'lineB2\n'), - 'gen2\n' - ]); - var expectedMap = node.toStringWithSourceMap({ - file: 'fileGen' - }).map; - expectedMap.setSourceContent('fileX', 'lineX1\nlineX2\n'); - expectedMap.setSourceContent('fileB', 'lineB1\nlineB2\n'); - expectedMap = expectedMap.toJSON(); - - // apply source map "mapStep1" to "mapStep2" - var generator = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(mapStep2)); - generator.applySourceMap(new SourceMapConsumer(mapStep1)); - var actualMap = generator.toJSON(); - - util.assertEqualMaps(assert, actualMap, expectedMap); - }; - - exports['test applySourceMap throws when file is missing'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'test.js' - }); - var map2 = new SourceMapGenerator(); - assert.throws(function() { - map.applySourceMap(new SourceMapConsumer(map2.toJSON())); - }); - }; - - exports['test the two additional parameters of applySourceMap'] = function (assert, util) { - // Assume the following directory structure: - // - // http://foo.org/ - // bar.coffee - // app/ - // coffee/ - // foo.coffee - // temp/ - // bundle.js - // temp_maps/ - // bundle.js.map - // public/ - // bundle.min.js - // bundle.min.js.map - // - // http://www.example.com/ - // baz.coffee - - var bundleMap = new SourceMapGenerator({ - file: 'bundle.js' - }); - bundleMap.addMapping({ - generated: { line: 3, column: 3 }, - original: { line: 2, column: 2 }, - source: '../../coffee/foo.coffee' - }); - bundleMap.setSourceContent('../../coffee/foo.coffee', 'foo coffee'); - bundleMap.addMapping({ - generated: { line: 13, column: 13 }, - original: { line: 12, column: 12 }, - source: '/bar.coffee' - }); - bundleMap.setSourceContent('/bar.coffee', 'bar coffee'); - bundleMap.addMapping({ - generated: { line: 23, column: 23 }, - original: { line: 22, column: 22 }, - source: 'http://www.example.com/baz.coffee' - }); - bundleMap.setSourceContent( - 'http://www.example.com/baz.coffee', - 'baz coffee' - ); - bundleMap = new SourceMapConsumer(bundleMap.toJSON()); - - var minifiedMap = new SourceMapGenerator({ - file: 'bundle.min.js', - sourceRoot: '..' - }); - minifiedMap.addMapping({ - generated: { line: 1, column: 1 }, - original: { line: 3, column: 3 }, - source: 'temp/bundle.js' - }); - minifiedMap.addMapping({ - generated: { line: 11, column: 11 }, - original: { line: 13, column: 13 }, - source: 'temp/bundle.js' - }); - minifiedMap.addMapping({ - generated: { line: 21, column: 21 }, - original: { line: 23, column: 23 }, - source: 'temp/bundle.js' - }); - minifiedMap = new SourceMapConsumer(minifiedMap.toJSON()); - - var expectedMap = function (sources) { - var map = new SourceMapGenerator({ - file: 'bundle.min.js', - sourceRoot: '..' - }); - map.addMapping({ - generated: { line: 1, column: 1 }, - original: { line: 2, column: 2 }, - source: sources[0] - }); - map.setSourceContent(sources[0], 'foo coffee'); - map.addMapping({ - generated: { line: 11, column: 11 }, - original: { line: 12, column: 12 }, - source: sources[1] - }); - map.setSourceContent(sources[1], 'bar coffee'); - map.addMapping({ - generated: { line: 21, column: 21 }, - original: { line: 22, column: 22 }, - source: sources[2] - }); - map.setSourceContent(sources[2], 'baz coffee'); - return map.toJSON(); - } - - var actualMap = function (aSourceMapPath) { - var map = SourceMapGenerator.fromSourceMap(minifiedMap); - // Note that relying on `bundleMap.file` (which is simply 'bundle.js') - // instead of supplying the second parameter wouldn't work here. - map.applySourceMap(bundleMap, '../temp/bundle.js', aSourceMapPath); - return map.toJSON(); - } - - util.assertEqualMaps(assert, actualMap('../temp/temp_maps'), expectedMap([ - 'coffee/foo.coffee', - '/bar.coffee', - 'http://www.example.com/baz.coffee' - ])); - - util.assertEqualMaps(assert, actualMap('/app/temp/temp_maps'), expectedMap([ - '/app/coffee/foo.coffee', - '/bar.coffee', - 'http://www.example.com/baz.coffee' - ])); - - util.assertEqualMaps(assert, actualMap('http://foo.org/app/temp/temp_maps'), expectedMap([ - 'http://foo.org/app/coffee/foo.coffee', - 'http://foo.org/bar.coffee', - 'http://www.example.com/baz.coffee' - ])); - - // If the third parameter is omitted or set to the current working - // directory we get incorrect source paths: - - util.assertEqualMaps(assert, actualMap(), expectedMap([ - '../coffee/foo.coffee', - '/bar.coffee', - 'http://www.example.com/baz.coffee' - ])); - - util.assertEqualMaps(assert, actualMap(''), expectedMap([ - '../coffee/foo.coffee', - '/bar.coffee', - 'http://www.example.com/baz.coffee' - ])); - - util.assertEqualMaps(assert, actualMap('.'), expectedMap([ - '../coffee/foo.coffee', - '/bar.coffee', - 'http://www.example.com/baz.coffee' - ])); - - util.assertEqualMaps(assert, actualMap('./'), expectedMap([ - '../coffee/foo.coffee', - '/bar.coffee', - 'http://www.example.com/baz.coffee' - ])); - }; - - exports['test applySourceMap name handling'] = function (assert, util) { - // Imagine some CoffeeScript code being compiled into JavaScript and then - // minified. - - var assertName = function(coffeeName, jsName, expectedName) { - var minifiedMap = new SourceMapGenerator({ - file: 'test.js.min' - }); - minifiedMap.addMapping({ - generated: { line: 1, column: 4 }, - original: { line: 1, column: 4 }, - source: 'test.js', - name: jsName - }); - - var coffeeMap = new SourceMapGenerator({ - file: 'test.js' - }); - coffeeMap.addMapping({ - generated: { line: 1, column: 4 }, - original: { line: 1, column: 0 }, - source: 'test.coffee', - name: coffeeName - }); - - minifiedMap.applySourceMap(new SourceMapConsumer(coffeeMap.toJSON())); - - new SourceMapConsumer(minifiedMap.toJSON()).eachMapping(function(mapping) { - assert.equal(mapping.name, expectedName); - }); - }; - - // `foo = 1` -> `var foo = 1;` -> `var a=1` - // CoffeeScript doesn’t rename variables, so there’s no need for it to - // provide names in its source maps. Minifiers do rename variables and - // therefore do provide names in their source maps. So that name should be - // retained if the original map lacks names. - assertName(null, 'foo', 'foo'); - - // `foo = 1` -> `var coffee$foo = 1;` -> `var a=1` - // Imagine that CoffeeScript prefixed all variables with `coffee$`. Even - // though the minifier then also provides a name, the original name is - // what corresponds to the source. - assertName('foo', 'coffee$foo', 'foo'); - - // `foo = 1` -> `var coffee$foo = 1;` -> `var coffee$foo=1` - // Minifiers can turn off variable mangling. Then there’s no need to - // provide names in the source map, but the names from the original map are - // still needed. - assertName('foo', null, 'foo'); - - // `foo = 1` -> `var foo = 1;` -> `var foo=1` - // No renaming at all. - assertName(null, null, null); - }; - - exports['test sorting with duplicate generated mappings'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'test.js' - }); - map.addMapping({ - generated: { line: 3, column: 0 }, - original: { line: 2, column: 0 }, - source: 'a.js' - }); - map.addMapping({ - generated: { line: 2, column: 0 } - }); - map.addMapping({ - generated: { line: 2, column: 0 } - }); - map.addMapping({ - generated: { line: 1, column: 0 }, - original: { line: 1, column: 0 }, - source: 'a.js' - }); - - util.assertEqualMaps(assert, map.toJSON(), { - version: 3, - file: 'test.js', - sources: ['a.js'], - names: [], - mappings: 'AAAA;A;AACA' - }); - }; - - exports['test ignore duplicate mappings.'] = function (assert, util) { - var init = { file: 'min.js', sourceRoot: '/the/root' }; - var map1, map2; - - // null original source location - var nullMapping1 = { - generated: { line: 1, column: 0 } - }; - var nullMapping2 = { - generated: { line: 2, column: 2 } - }; - - map1 = new SourceMapGenerator(init); - map2 = new SourceMapGenerator(init); - - map1.addMapping(nullMapping1); - map1.addMapping(nullMapping1); - - map2.addMapping(nullMapping1); - - util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); - - map1.addMapping(nullMapping2); - map1.addMapping(nullMapping1); - - map2.addMapping(nullMapping2); - - util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); - - // original source location - var srcMapping1 = { - generated: { line: 1, column: 0 }, - original: { line: 11, column: 0 }, - source: 'srcMapping1.js' - }; - var srcMapping2 = { - generated: { line: 2, column: 2 }, - original: { line: 11, column: 0 }, - source: 'srcMapping2.js' - }; - - map1 = new SourceMapGenerator(init); - map2 = new SourceMapGenerator(init); - - map1.addMapping(srcMapping1); - map1.addMapping(srcMapping1); - - map2.addMapping(srcMapping1); - - util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); - - map1.addMapping(srcMapping2); - map1.addMapping(srcMapping1); - - map2.addMapping(srcMapping2); - - util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); - - // full original source and name information - var fullMapping1 = { - generated: { line: 1, column: 0 }, - original: { line: 11, column: 0 }, - source: 'fullMapping1.js', - name: 'fullMapping1' - }; - var fullMapping2 = { - generated: { line: 2, column: 2 }, - original: { line: 11, column: 0 }, - source: 'fullMapping2.js', - name: 'fullMapping2' - }; - - map1 = new SourceMapGenerator(init); - map2 = new SourceMapGenerator(init); - - map1.addMapping(fullMapping1); - map1.addMapping(fullMapping1); - - map2.addMapping(fullMapping1); - - util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); - - map1.addMapping(fullMapping2); - map1.addMapping(fullMapping1); - - map2.addMapping(fullMapping2); - - util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); - }; - - exports['test github issue #72, check for duplicate names or sources'] = function (assert, util) { - var map = new SourceMapGenerator({ - file: 'test.js' - }); - map.addMapping({ - generated: { line: 1, column: 1 }, - original: { line: 2, column: 2 }, - source: 'a.js', - name: 'foo' - }); - map.addMapping({ - generated: { line: 3, column: 3 }, - original: { line: 4, column: 4 }, - source: 'a.js', - name: 'foo' - }); - util.assertEqualMaps(assert, map.toJSON(), { - version: 3, - file: 'test.js', - sources: ['a.js'], - names: ['foo'], - mappings: 'CACEA;;GAEEA' - }); - }; - - exports['test setting sourcesContent to null when already null'] = function (assert, util) { - var smg = new SourceMapGenerator({ file: "foo.js" }); - assert.doesNotThrow(function() { - smg.setSourceContent("bar.js", null); - }); - }; - -}); diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-node.js b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-node.js deleted file mode 100644 index 139af4e..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-node.js +++ /dev/null @@ -1,612 +0,0 @@ -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { - - var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; - var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; - var SourceNode = require('../../lib/source-map/source-node').SourceNode; - - function forEachNewline(fn) { - return function (assert, util) { - ['\n', '\r\n'].forEach(fn.bind(null, assert, util)); - } - } - - exports['test .add()'] = function (assert, util) { - var node = new SourceNode(null, null, null); - - // Adding a string works. - node.add('function noop() {}'); - - // Adding another source node works. - node.add(new SourceNode(null, null, null)); - - // Adding an array works. - node.add(['function foo() {', - new SourceNode(null, null, null, - 'return 10;'), - '}']); - - // Adding other stuff doesn't. - assert.throws(function () { - node.add({}); - }); - assert.throws(function () { - node.add(function () {}); - }); - }; - - exports['test .prepend()'] = function (assert, util) { - var node = new SourceNode(null, null, null); - - // Prepending a string works. - node.prepend('function noop() {}'); - assert.equal(node.children[0], 'function noop() {}'); - assert.equal(node.children.length, 1); - - // Prepending another source node works. - node.prepend(new SourceNode(null, null, null)); - assert.equal(node.children[0], ''); - assert.equal(node.children[1], 'function noop() {}'); - assert.equal(node.children.length, 2); - - // Prepending an array works. - node.prepend(['function foo() {', - new SourceNode(null, null, null, - 'return 10;'), - '}']); - assert.equal(node.children[0], 'function foo() {'); - assert.equal(node.children[1], 'return 10;'); - assert.equal(node.children[2], '}'); - assert.equal(node.children[3], ''); - assert.equal(node.children[4], 'function noop() {}'); - assert.equal(node.children.length, 5); - - // Prepending other stuff doesn't. - assert.throws(function () { - node.prepend({}); - }); - assert.throws(function () { - node.prepend(function () {}); - }); - }; - - exports['test .toString()'] = function (assert, util) { - assert.equal((new SourceNode(null, null, null, - ['function foo() {', - new SourceNode(null, null, null, 'return 10;'), - '}'])).toString(), - 'function foo() {return 10;}'); - }; - - exports['test .join()'] = function (assert, util) { - assert.equal((new SourceNode(null, null, null, - ['a', 'b', 'c', 'd'])).join(', ').toString(), - 'a, b, c, d'); - }; - - exports['test .walk()'] = function (assert, util) { - var node = new SourceNode(null, null, null, - ['(function () {\n', - ' ', new SourceNode(1, 0, 'a.js', ['someCall()']), ';\n', - ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';\n', - '}());']); - var expected = [ - { str: '(function () {\n', source: null, line: null, column: null }, - { str: ' ', source: null, line: null, column: null }, - { str: 'someCall()', source: 'a.js', line: 1, column: 0 }, - { str: ';\n', source: null, line: null, column: null }, - { str: ' ', source: null, line: null, column: null }, - { str: 'if (foo) bar()', source: 'b.js', line: 2, column: 0 }, - { str: ';\n', source: null, line: null, column: null }, - { str: '}());', source: null, line: null, column: null }, - ]; - var i = 0; - node.walk(function (chunk, loc) { - assert.equal(expected[i].str, chunk); - assert.equal(expected[i].source, loc.source); - assert.equal(expected[i].line, loc.line); - assert.equal(expected[i].column, loc.column); - i++; - }); - }; - - exports['test .replaceRight'] = function (assert, util) { - var node; - - // Not nested - node = new SourceNode(null, null, null, 'hello world'); - node.replaceRight(/world/, 'universe'); - assert.equal(node.toString(), 'hello universe'); - - // Nested - node = new SourceNode(null, null, null, - [new SourceNode(null, null, null, 'hey sexy mama, '), - new SourceNode(null, null, null, 'want to kill all humans?')]); - node.replaceRight(/kill all humans/, 'watch Futurama'); - assert.equal(node.toString(), 'hey sexy mama, want to watch Futurama?'); - }; - - exports['test .toStringWithSourceMap()'] = forEachNewline(function (assert, util, nl) { - var node = new SourceNode(null, null, null, - ['(function () {' + nl, - ' ', - new SourceNode(1, 0, 'a.js', 'someCall', 'originalCall'), - new SourceNode(1, 8, 'a.js', '()'), - ';' + nl, - ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';' + nl, - '}());']); - var result = node.toStringWithSourceMap({ - file: 'foo.js' - }); - - assert.equal(result.code, [ - '(function () {', - ' someCall();', - ' if (foo) bar();', - '}());' - ].join(nl)); - - var map = result.map; - var mapWithoutOptions = node.toStringWithSourceMap().map; - - assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); - assert.ok(mapWithoutOptions instanceof SourceMapGenerator, 'mapWithoutOptions instanceof SourceMapGenerator'); - assert.ok(!('file' in mapWithoutOptions)); - mapWithoutOptions._file = 'foo.js'; - util.assertEqualMaps(assert, map.toJSON(), mapWithoutOptions.toJSON()); - - map = new SourceMapConsumer(map.toString()); - - var actual; - - actual = map.originalPositionFor({ - line: 1, - column: 4 - }); - assert.equal(actual.source, null); - assert.equal(actual.line, null); - assert.equal(actual.column, null); - - actual = map.originalPositionFor({ - line: 2, - column: 2 - }); - assert.equal(actual.source, 'a.js'); - assert.equal(actual.line, 1); - assert.equal(actual.column, 0); - assert.equal(actual.name, 'originalCall'); - - actual = map.originalPositionFor({ - line: 3, - column: 2 - }); - assert.equal(actual.source, 'b.js'); - assert.equal(actual.line, 2); - assert.equal(actual.column, 0); - - actual = map.originalPositionFor({ - line: 3, - column: 16 - }); - assert.equal(actual.source, null); - assert.equal(actual.line, null); - assert.equal(actual.column, null); - - actual = map.originalPositionFor({ - line: 4, - column: 2 - }); - assert.equal(actual.source, null); - assert.equal(actual.line, null); - assert.equal(actual.column, null); - }); - - exports['test .fromStringWithSourceMap()'] = forEachNewline(function (assert, util, nl) { - var testCode = util.testGeneratedCode.replace(/\n/g, nl); - var node = SourceNode.fromStringWithSourceMap( - testCode, - new SourceMapConsumer(util.testMap)); - - var result = node.toStringWithSourceMap({ - file: 'min.js' - }); - var map = result.map; - var code = result.code; - - assert.equal(code, testCode); - assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); - map = map.toJSON(); - assert.equal(map.version, util.testMap.version); - assert.equal(map.file, util.testMap.file); - assert.equal(map.mappings, util.testMap.mappings); - }); - - exports['test .fromStringWithSourceMap() empty map'] = forEachNewline(function (assert, util, nl) { - var node = SourceNode.fromStringWithSourceMap( - util.testGeneratedCode.replace(/\n/g, nl), - new SourceMapConsumer(util.emptyMap)); - var result = node.toStringWithSourceMap({ - file: 'min.js' - }); - var map = result.map; - var code = result.code; - - assert.equal(code, util.testGeneratedCode.replace(/\n/g, nl)); - assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); - map = map.toJSON(); - assert.equal(map.version, util.emptyMap.version); - assert.equal(map.file, util.emptyMap.file); - assert.equal(map.mappings.length, util.emptyMap.mappings.length); - assert.equal(map.mappings, util.emptyMap.mappings); - }); - - exports['test .fromStringWithSourceMap() complex version'] = forEachNewline(function (assert, util, nl) { - var input = new SourceNode(null, null, null, [ - "(function() {" + nl, - " var Test = {};" + nl, - " ", new SourceNode(1, 0, "a.js", "Test.A = { value: 1234 };" + nl), - " ", new SourceNode(2, 0, "a.js", "Test.A.x = 'xyz';"), nl, - "}());" + nl, - "/* Generated Source */"]); - input = input.toStringWithSourceMap({ - file: 'foo.js' - }); - - var node = SourceNode.fromStringWithSourceMap( - input.code, - new SourceMapConsumer(input.map.toString())); - - var result = node.toStringWithSourceMap({ - file: 'foo.js' - }); - var map = result.map; - var code = result.code; - - assert.equal(code, input.code); - assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); - map = map.toJSON(); - var inputMap = input.map.toJSON(); - util.assertEqualMaps(assert, map, inputMap); - }); - - exports['test .fromStringWithSourceMap() third argument'] = function (assert, util) { - // Assume the following directory structure: - // - // http://foo.org/ - // bar.coffee - // app/ - // coffee/ - // foo.coffee - // coffeeBundle.js # Made from {foo,bar,baz}.coffee - // maps/ - // coffeeBundle.js.map - // js/ - // foo.js - // public/ - // app.js # Made from {foo,coffeeBundle}.js - // app.js.map - // - // http://www.example.com/ - // baz.coffee - - var coffeeBundle = new SourceNode(1, 0, 'foo.coffee', 'foo(coffee);\n'); - coffeeBundle.setSourceContent('foo.coffee', 'foo coffee'); - coffeeBundle.add(new SourceNode(2, 0, '/bar.coffee', 'bar(coffee);\n')); - coffeeBundle.add(new SourceNode(3, 0, 'http://www.example.com/baz.coffee', 'baz(coffee);')); - coffeeBundle = coffeeBundle.toStringWithSourceMap({ - file: 'foo.js', - sourceRoot: '..' - }); - - var foo = new SourceNode(1, 0, 'foo.js', 'foo(js);'); - - var test = function(relativePath, expectedSources) { - var app = new SourceNode(); - app.add(SourceNode.fromStringWithSourceMap( - coffeeBundle.code, - new SourceMapConsumer(coffeeBundle.map.toString()), - relativePath)); - app.add(foo); - var i = 0; - app.walk(function (chunk, loc) { - assert.equal(loc.source, expectedSources[i]); - i++; - }); - app.walkSourceContents(function (sourceFile, sourceContent) { - assert.equal(sourceFile, expectedSources[0]); - assert.equal(sourceContent, 'foo coffee'); - }) - }; - - test('../coffee/maps', [ - '../coffee/foo.coffee', - '/bar.coffee', - 'http://www.example.com/baz.coffee', - 'foo.js' - ]); - - // If the third parameter is omitted or set to the current working - // directory we get incorrect source paths: - - test(undefined, [ - '../foo.coffee', - '/bar.coffee', - 'http://www.example.com/baz.coffee', - 'foo.js' - ]); - - test('', [ - '../foo.coffee', - '/bar.coffee', - 'http://www.example.com/baz.coffee', - 'foo.js' - ]); - - test('.', [ - '../foo.coffee', - '/bar.coffee', - 'http://www.example.com/baz.coffee', - 'foo.js' - ]); - - test('./', [ - '../foo.coffee', - '/bar.coffee', - 'http://www.example.com/baz.coffee', - 'foo.js' - ]); - }; - - exports['test .toStringWithSourceMap() merging duplicate mappings'] = forEachNewline(function (assert, util, nl) { - var input = new SourceNode(null, null, null, [ - new SourceNode(1, 0, "a.js", "(function"), - new SourceNode(1, 0, "a.js", "() {" + nl), - " ", - new SourceNode(1, 0, "a.js", "var Test = "), - new SourceNode(1, 0, "b.js", "{};" + nl), - new SourceNode(2, 0, "b.js", "Test"), - new SourceNode(2, 0, "b.js", ".A", "A"), - new SourceNode(2, 20, "b.js", " = { value: ", "A"), - "1234", - new SourceNode(2, 40, "b.js", " };" + nl, "A"), - "}());" + nl, - "/* Generated Source */" - ]); - input = input.toStringWithSourceMap({ - file: 'foo.js' - }); - - assert.equal(input.code, [ - "(function() {", - " var Test = {};", - "Test.A = { value: 1234 };", - "}());", - "/* Generated Source */" - ].join(nl)) - - var correctMap = new SourceMapGenerator({ - file: 'foo.js' - }); - correctMap.addMapping({ - generated: { line: 1, column: 0 }, - source: 'a.js', - original: { line: 1, column: 0 } - }); - // Here is no need for a empty mapping, - // because mappings ends at eol - correctMap.addMapping({ - generated: { line: 2, column: 2 }, - source: 'a.js', - original: { line: 1, column: 0 } - }); - correctMap.addMapping({ - generated: { line: 2, column: 13 }, - source: 'b.js', - original: { line: 1, column: 0 } - }); - correctMap.addMapping({ - generated: { line: 3, column: 0 }, - source: 'b.js', - original: { line: 2, column: 0 } - }); - correctMap.addMapping({ - generated: { line: 3, column: 4 }, - source: 'b.js', - name: 'A', - original: { line: 2, column: 0 } - }); - correctMap.addMapping({ - generated: { line: 3, column: 6 }, - source: 'b.js', - name: 'A', - original: { line: 2, column: 20 } - }); - // This empty mapping is required, - // because there is a hole in the middle of the line - correctMap.addMapping({ - generated: { line: 3, column: 18 } - }); - correctMap.addMapping({ - generated: { line: 3, column: 22 }, - source: 'b.js', - name: 'A', - original: { line: 2, column: 40 } - }); - // Here is no need for a empty mapping, - // because mappings ends at eol - - var inputMap = input.map.toJSON(); - correctMap = correctMap.toJSON(); - util.assertEqualMaps(assert, inputMap, correctMap); - }); - - exports['test .toStringWithSourceMap() multi-line SourceNodes'] = forEachNewline(function (assert, util, nl) { - var input = new SourceNode(null, null, null, [ - new SourceNode(1, 0, "a.js", "(function() {" + nl + "var nextLine = 1;" + nl + "anotherLine();" + nl), - new SourceNode(2, 2, "b.js", "Test.call(this, 123);" + nl), - new SourceNode(2, 2, "b.js", "this['stuff'] = 'v';" + nl), - new SourceNode(2, 2, "b.js", "anotherLine();" + nl), - "/*" + nl + "Generated" + nl + "Source" + nl + "*/" + nl, - new SourceNode(3, 4, "c.js", "anotherLine();" + nl), - "/*" + nl + "Generated" + nl + "Source" + nl + "*/" - ]); - input = input.toStringWithSourceMap({ - file: 'foo.js' - }); - - assert.equal(input.code, [ - "(function() {", - "var nextLine = 1;", - "anotherLine();", - "Test.call(this, 123);", - "this['stuff'] = 'v';", - "anotherLine();", - "/*", - "Generated", - "Source", - "*/", - "anotherLine();", - "/*", - "Generated", - "Source", - "*/" - ].join(nl)); - - var correctMap = new SourceMapGenerator({ - file: 'foo.js' - }); - correctMap.addMapping({ - generated: { line: 1, column: 0 }, - source: 'a.js', - original: { line: 1, column: 0 } - }); - correctMap.addMapping({ - generated: { line: 2, column: 0 }, - source: 'a.js', - original: { line: 1, column: 0 } - }); - correctMap.addMapping({ - generated: { line: 3, column: 0 }, - source: 'a.js', - original: { line: 1, column: 0 } - }); - correctMap.addMapping({ - generated: { line: 4, column: 0 }, - source: 'b.js', - original: { line: 2, column: 2 } - }); - correctMap.addMapping({ - generated: { line: 5, column: 0 }, - source: 'b.js', - original: { line: 2, column: 2 } - }); - correctMap.addMapping({ - generated: { line: 6, column: 0 }, - source: 'b.js', - original: { line: 2, column: 2 } - }); - correctMap.addMapping({ - generated: { line: 11, column: 0 }, - source: 'c.js', - original: { line: 3, column: 4 } - }); - - var inputMap = input.map.toJSON(); - correctMap = correctMap.toJSON(); - util.assertEqualMaps(assert, inputMap, correctMap); - }); - - exports['test .toStringWithSourceMap() with empty string'] = function (assert, util) { - var node = new SourceNode(1, 0, 'empty.js', ''); - var result = node.toStringWithSourceMap(); - assert.equal(result.code, ''); - }; - - exports['test .toStringWithSourceMap() with consecutive newlines'] = forEachNewline(function (assert, util, nl) { - var input = new SourceNode(null, null, null, [ - "/***/" + nl + nl, - new SourceNode(1, 0, "a.js", "'use strict';" + nl), - new SourceNode(2, 0, "a.js", "a();"), - ]); - input = input.toStringWithSourceMap({ - file: 'foo.js' - }); - - assert.equal(input.code, [ - "/***/", - "", - "'use strict';", - "a();", - ].join(nl)); - - var correctMap = new SourceMapGenerator({ - file: 'foo.js' - }); - correctMap.addMapping({ - generated: { line: 3, column: 0 }, - source: 'a.js', - original: { line: 1, column: 0 } - }); - correctMap.addMapping({ - generated: { line: 4, column: 0 }, - source: 'a.js', - original: { line: 2, column: 0 } - }); - - var inputMap = input.map.toJSON(); - correctMap = correctMap.toJSON(); - util.assertEqualMaps(assert, inputMap, correctMap); - }); - - exports['test setSourceContent with toStringWithSourceMap'] = function (assert, util) { - var aNode = new SourceNode(1, 1, 'a.js', 'a'); - aNode.setSourceContent('a.js', 'someContent'); - var node = new SourceNode(null, null, null, - ['(function () {\n', - ' ', aNode, - ' ', new SourceNode(1, 1, 'b.js', 'b'), - '}());']); - node.setSourceContent('b.js', 'otherContent'); - var map = node.toStringWithSourceMap({ - file: 'foo.js' - }).map; - - assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); - map = new SourceMapConsumer(map.toString()); - - assert.equal(map.sources.length, 2); - assert.equal(map.sources[0], 'a.js'); - assert.equal(map.sources[1], 'b.js'); - assert.equal(map.sourcesContent.length, 2); - assert.equal(map.sourcesContent[0], 'someContent'); - assert.equal(map.sourcesContent[1], 'otherContent'); - }; - - exports['test walkSourceContents'] = function (assert, util) { - var aNode = new SourceNode(1, 1, 'a.js', 'a'); - aNode.setSourceContent('a.js', 'someContent'); - var node = new SourceNode(null, null, null, - ['(function () {\n', - ' ', aNode, - ' ', new SourceNode(1, 1, 'b.js', 'b'), - '}());']); - node.setSourceContent('b.js', 'otherContent'); - var results = []; - node.walkSourceContents(function (sourceFile, sourceContent) { - results.push([sourceFile, sourceContent]); - }); - assert.equal(results.length, 2); - assert.equal(results[0][0], 'a.js'); - assert.equal(results[0][1], 'someContent'); - assert.equal(results[1][0], 'b.js'); - assert.equal(results[1][1], 'otherContent'); - }; -}); diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-util.js b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-util.js deleted file mode 100644 index 997d1a2..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/test-util.js +++ /dev/null @@ -1,216 +0,0 @@ -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2014 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { - - var libUtil = require('../../lib/source-map/util'); - - exports['test urls'] = function (assert, util) { - var assertUrl = function (url) { - assert.equal(url, libUtil.urlGenerate(libUtil.urlParse(url))); - }; - assertUrl('http://'); - assertUrl('http://www.example.com'); - assertUrl('http://user:pass@www.example.com'); - assertUrl('http://www.example.com:80'); - assertUrl('http://www.example.com/'); - assertUrl('http://www.example.com/foo/bar'); - assertUrl('http://www.example.com/foo/bar/'); - assertUrl('http://user:pass@www.example.com:80/foo/bar/'); - - assertUrl('//'); - assertUrl('//www.example.com'); - assertUrl('file:///www.example.com'); - - assert.equal(libUtil.urlParse(''), null); - assert.equal(libUtil.urlParse('.'), null); - assert.equal(libUtil.urlParse('..'), null); - assert.equal(libUtil.urlParse('a'), null); - assert.equal(libUtil.urlParse('a/b'), null); - assert.equal(libUtil.urlParse('a//b'), null); - assert.equal(libUtil.urlParse('/a'), null); - assert.equal(libUtil.urlParse('data:foo,bar'), null); - }; - - exports['test normalize()'] = function (assert, util) { - assert.equal(libUtil.normalize('/..'), '/'); - assert.equal(libUtil.normalize('/../'), '/'); - assert.equal(libUtil.normalize('/../../../..'), '/'); - assert.equal(libUtil.normalize('/../../../../a/b/c'), '/a/b/c'); - assert.equal(libUtil.normalize('/a/b/c/../../../d/../../e'), '/e'); - - assert.equal(libUtil.normalize('..'), '..'); - assert.equal(libUtil.normalize('../'), '../'); - assert.equal(libUtil.normalize('../../a/'), '../../a/'); - assert.equal(libUtil.normalize('a/..'), '.'); - assert.equal(libUtil.normalize('a/../../..'), '../..'); - - assert.equal(libUtil.normalize('/.'), '/'); - assert.equal(libUtil.normalize('/./'), '/'); - assert.equal(libUtil.normalize('/./././.'), '/'); - assert.equal(libUtil.normalize('/././././a/b/c'), '/a/b/c'); - assert.equal(libUtil.normalize('/a/b/c/./././d/././e'), '/a/b/c/d/e'); - - assert.equal(libUtil.normalize(''), '.'); - assert.equal(libUtil.normalize('.'), '.'); - assert.equal(libUtil.normalize('./'), '.'); - assert.equal(libUtil.normalize('././a'), 'a'); - assert.equal(libUtil.normalize('a/./'), 'a/'); - assert.equal(libUtil.normalize('a/././.'), 'a'); - - assert.equal(libUtil.normalize('/a/b//c////d/////'), '/a/b/c/d/'); - assert.equal(libUtil.normalize('///a/b//c////d/////'), '///a/b/c/d/'); - assert.equal(libUtil.normalize('a/b//c////d'), 'a/b/c/d'); - - assert.equal(libUtil.normalize('.///.././../a/b//./..'), '../../a') - - assert.equal(libUtil.normalize('http://www.example.com'), 'http://www.example.com'); - assert.equal(libUtil.normalize('http://www.example.com/'), 'http://www.example.com/'); - assert.equal(libUtil.normalize('http://www.example.com/./..//a/b/c/.././d//'), 'http://www.example.com/a/b/d/'); - }; - - exports['test join()'] = function (assert, util) { - assert.equal(libUtil.join('a', 'b'), 'a/b'); - assert.equal(libUtil.join('a/', 'b'), 'a/b'); - assert.equal(libUtil.join('a//', 'b'), 'a/b'); - assert.equal(libUtil.join('a', 'b/'), 'a/b/'); - assert.equal(libUtil.join('a', 'b//'), 'a/b/'); - assert.equal(libUtil.join('a/', '/b'), '/b'); - assert.equal(libUtil.join('a//', '//b'), '//b'); - - assert.equal(libUtil.join('a', '..'), '.'); - assert.equal(libUtil.join('a', '../b'), 'b'); - assert.equal(libUtil.join('a/b', '../c'), 'a/c'); - - assert.equal(libUtil.join('a', '.'), 'a'); - assert.equal(libUtil.join('a', './b'), 'a/b'); - assert.equal(libUtil.join('a/b', './c'), 'a/b/c'); - - assert.equal(libUtil.join('a', 'http://www.example.com'), 'http://www.example.com'); - assert.equal(libUtil.join('a', 'data:foo,bar'), 'data:foo,bar'); - - - assert.equal(libUtil.join('', 'b'), 'b'); - assert.equal(libUtil.join('.', 'b'), 'b'); - assert.equal(libUtil.join('', 'b/'), 'b/'); - assert.equal(libUtil.join('.', 'b/'), 'b/'); - assert.equal(libUtil.join('', 'b//'), 'b/'); - assert.equal(libUtil.join('.', 'b//'), 'b/'); - - assert.equal(libUtil.join('', '..'), '..'); - assert.equal(libUtil.join('.', '..'), '..'); - assert.equal(libUtil.join('', '../b'), '../b'); - assert.equal(libUtil.join('.', '../b'), '../b'); - - assert.equal(libUtil.join('', '.'), '.'); - assert.equal(libUtil.join('.', '.'), '.'); - assert.equal(libUtil.join('', './b'), 'b'); - assert.equal(libUtil.join('.', './b'), 'b'); - - assert.equal(libUtil.join('', 'http://www.example.com'), 'http://www.example.com'); - assert.equal(libUtil.join('.', 'http://www.example.com'), 'http://www.example.com'); - assert.equal(libUtil.join('', 'data:foo,bar'), 'data:foo,bar'); - assert.equal(libUtil.join('.', 'data:foo,bar'), 'data:foo,bar'); - - - assert.equal(libUtil.join('..', 'b'), '../b'); - assert.equal(libUtil.join('..', 'b/'), '../b/'); - assert.equal(libUtil.join('..', 'b//'), '../b/'); - - assert.equal(libUtil.join('..', '..'), '../..'); - assert.equal(libUtil.join('..', '../b'), '../../b'); - - assert.equal(libUtil.join('..', '.'), '..'); - assert.equal(libUtil.join('..', './b'), '../b'); - - assert.equal(libUtil.join('..', 'http://www.example.com'), 'http://www.example.com'); - assert.equal(libUtil.join('..', 'data:foo,bar'), 'data:foo,bar'); - - - assert.equal(libUtil.join('a', ''), 'a'); - assert.equal(libUtil.join('a', '.'), 'a'); - assert.equal(libUtil.join('a/', ''), 'a'); - assert.equal(libUtil.join('a/', '.'), 'a'); - assert.equal(libUtil.join('a//', ''), 'a'); - assert.equal(libUtil.join('a//', '.'), 'a'); - assert.equal(libUtil.join('/a', ''), '/a'); - assert.equal(libUtil.join('/a', '.'), '/a'); - assert.equal(libUtil.join('', ''), '.'); - assert.equal(libUtil.join('.', ''), '.'); - assert.equal(libUtil.join('.', ''), '.'); - assert.equal(libUtil.join('.', '.'), '.'); - assert.equal(libUtil.join('..', ''), '..'); - assert.equal(libUtil.join('..', '.'), '..'); - assert.equal(libUtil.join('http://foo.org/a', ''), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org/a', '.'), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org/a/', ''), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org/a/', '.'), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org/a//', ''), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org/a//', '.'), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org', ''), 'http://foo.org/'); - assert.equal(libUtil.join('http://foo.org', '.'), 'http://foo.org/'); - assert.equal(libUtil.join('http://foo.org/', ''), 'http://foo.org/'); - assert.equal(libUtil.join('http://foo.org/', '.'), 'http://foo.org/'); - assert.equal(libUtil.join('http://foo.org//', ''), 'http://foo.org/'); - assert.equal(libUtil.join('http://foo.org//', '.'), 'http://foo.org/'); - assert.equal(libUtil.join('//www.example.com', ''), '//www.example.com/'); - assert.equal(libUtil.join('//www.example.com', '.'), '//www.example.com/'); - - - assert.equal(libUtil.join('http://foo.org/a', 'b'), 'http://foo.org/a/b'); - assert.equal(libUtil.join('http://foo.org/a/', 'b'), 'http://foo.org/a/b'); - assert.equal(libUtil.join('http://foo.org/a//', 'b'), 'http://foo.org/a/b'); - assert.equal(libUtil.join('http://foo.org/a', 'b/'), 'http://foo.org/a/b/'); - assert.equal(libUtil.join('http://foo.org/a', 'b//'), 'http://foo.org/a/b/'); - assert.equal(libUtil.join('http://foo.org/a/', '/b'), 'http://foo.org/b'); - assert.equal(libUtil.join('http://foo.org/a//', '//b'), 'http://b'); - - assert.equal(libUtil.join('http://foo.org/a', '..'), 'http://foo.org/'); - assert.equal(libUtil.join('http://foo.org/a', '../b'), 'http://foo.org/b'); - assert.equal(libUtil.join('http://foo.org/a/b', '../c'), 'http://foo.org/a/c'); - - assert.equal(libUtil.join('http://foo.org/a', '.'), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org/a', './b'), 'http://foo.org/a/b'); - assert.equal(libUtil.join('http://foo.org/a/b', './c'), 'http://foo.org/a/b/c'); - - assert.equal(libUtil.join('http://foo.org/a', 'http://www.example.com'), 'http://www.example.com'); - assert.equal(libUtil.join('http://foo.org/a', 'data:foo,bar'), 'data:foo,bar'); - - - assert.equal(libUtil.join('http://foo.org', 'a'), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org/', 'a'), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org//', 'a'), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org', '/a'), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org/', '/a'), 'http://foo.org/a'); - assert.equal(libUtil.join('http://foo.org//', '/a'), 'http://foo.org/a'); - - - assert.equal(libUtil.join('http://', 'www.example.com'), 'http://www.example.com'); - assert.equal(libUtil.join('file:///', 'www.example.com'), 'file:///www.example.com'); - assert.equal(libUtil.join('http://', 'ftp://example.com'), 'ftp://example.com'); - - assert.equal(libUtil.join('http://www.example.com', '//foo.org/bar'), 'http://foo.org/bar'); - assert.equal(libUtil.join('//www.example.com', '//foo.org/bar'), '//foo.org/bar'); - }; - - // TODO Issue #128: Define and test this function properly. - exports['test relative()'] = function (assert, util) { - assert.equal(libUtil.relative('/the/root', '/the/root/one.js'), 'one.js'); - assert.equal(libUtil.relative('/the/root', '/the/rootone.js'), '/the/rootone.js'); - - assert.equal(libUtil.relative('', '/the/root/one.js'), '/the/root/one.js'); - assert.equal(libUtil.relative('.', '/the/root/one.js'), '/the/root/one.js'); - assert.equal(libUtil.relative('', 'the/root/one.js'), 'the/root/one.js'); - assert.equal(libUtil.relative('.', 'the/root/one.js'), 'the/root/one.js'); - - assert.equal(libUtil.relative('/', '/the/root/one.js'), 'the/root/one.js'); - assert.equal(libUtil.relative('/', 'the/root/one.js'), 'the/root/one.js'); - }; - -}); diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/util.js b/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/util.js deleted file mode 100644 index 56bbe2c..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/source-map/test/source-map/util.js +++ /dev/null @@ -1,192 +0,0 @@ -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ -if (typeof define !== 'function') { - var define = require('amdefine')(module, require); -} -define(function (require, exports, module) { - - var util = require('../../lib/source-map/util'); - - // This is a test mapping which maps functions from two different files - // (one.js and two.js) to a minified generated source. - // - // Here is one.js: - // - // ONE.foo = function (bar) { - // return baz(bar); - // }; - // - // Here is two.js: - // - // TWO.inc = function (n) { - // return n + 1; - // }; - // - // And here is the generated code (min.js): - // - // ONE.foo=function(a){return baz(a);}; - // TWO.inc=function(a){return a+1;}; - exports.testGeneratedCode = " ONE.foo=function(a){return baz(a);};\n"+ - " TWO.inc=function(a){return a+1;};"; - exports.testMap = { - version: 3, - file: 'min.js', - names: ['bar', 'baz', 'n'], - sources: ['one.js', 'two.js'], - sourceRoot: '/the/root', - mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' - }; - exports.testMapNoSourceRoot = { - version: 3, - file: 'min.js', - names: ['bar', 'baz', 'n'], - sources: ['one.js', 'two.js'], - mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' - }; - exports.testMapEmptySourceRoot = { - version: 3, - file: 'min.js', - names: ['bar', 'baz', 'n'], - sources: ['one.js', 'two.js'], - sourceRoot: '', - mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' - }; - exports.testMapWithSourcesContent = { - version: 3, - file: 'min.js', - names: ['bar', 'baz', 'n'], - sources: ['one.js', 'two.js'], - sourcesContent: [ - ' ONE.foo = function (bar) {\n' + - ' return baz(bar);\n' + - ' };', - ' TWO.inc = function (n) {\n' + - ' return n + 1;\n' + - ' };' - ], - sourceRoot: '/the/root', - mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' - }; - exports.testMapRelativeSources = { - version: 3, - file: 'min.js', - names: ['bar', 'baz', 'n'], - sources: ['./one.js', './two.js'], - sourcesContent: [ - ' ONE.foo = function (bar) {\n' + - ' return baz(bar);\n' + - ' };', - ' TWO.inc = function (n) {\n' + - ' return n + 1;\n' + - ' };' - ], - sourceRoot: '/the/root', - mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' - }; - exports.emptyMap = { - version: 3, - file: 'min.js', - names: [], - sources: [], - mappings: '' - }; - - - function assertMapping(generatedLine, generatedColumn, originalSource, - originalLine, originalColumn, name, map, assert, - dontTestGenerated, dontTestOriginal) { - if (!dontTestOriginal) { - var origMapping = map.originalPositionFor({ - line: generatedLine, - column: generatedColumn - }); - assert.equal(origMapping.name, name, - 'Incorrect name, expected ' + JSON.stringify(name) - + ', got ' + JSON.stringify(origMapping.name)); - assert.equal(origMapping.line, originalLine, - 'Incorrect line, expected ' + JSON.stringify(originalLine) - + ', got ' + JSON.stringify(origMapping.line)); - assert.equal(origMapping.column, originalColumn, - 'Incorrect column, expected ' + JSON.stringify(originalColumn) - + ', got ' + JSON.stringify(origMapping.column)); - - var expectedSource; - - if (originalSource && map.sourceRoot && originalSource.indexOf(map.sourceRoot) === 0) { - expectedSource = originalSource; - } else if (originalSource) { - expectedSource = map.sourceRoot - ? util.join(map.sourceRoot, originalSource) - : originalSource; - } else { - expectedSource = null; - } - - assert.equal(origMapping.source, expectedSource, - 'Incorrect source, expected ' + JSON.stringify(expectedSource) - + ', got ' + JSON.stringify(origMapping.source)); - } - - if (!dontTestGenerated) { - var genMapping = map.generatedPositionFor({ - source: originalSource, - line: originalLine, - column: originalColumn - }); - assert.equal(genMapping.line, generatedLine, - 'Incorrect line, expected ' + JSON.stringify(generatedLine) - + ', got ' + JSON.stringify(genMapping.line)); - assert.equal(genMapping.column, generatedColumn, - 'Incorrect column, expected ' + JSON.stringify(generatedColumn) - + ', got ' + JSON.stringify(genMapping.column)); - } - } - exports.assertMapping = assertMapping; - - function assertEqualMaps(assert, actualMap, expectedMap) { - assert.equal(actualMap.version, expectedMap.version, "version mismatch"); - assert.equal(actualMap.file, expectedMap.file, "file mismatch"); - assert.equal(actualMap.names.length, - expectedMap.names.length, - "names length mismatch: " + - actualMap.names.join(", ") + " != " + expectedMap.names.join(", ")); - for (var i = 0; i < actualMap.names.length; i++) { - assert.equal(actualMap.names[i], - expectedMap.names[i], - "names[" + i + "] mismatch: " + - actualMap.names.join(", ") + " != " + expectedMap.names.join(", ")); - } - assert.equal(actualMap.sources.length, - expectedMap.sources.length, - "sources length mismatch: " + - actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", ")); - for (var i = 0; i < actualMap.sources.length; i++) { - assert.equal(actualMap.sources[i], - expectedMap.sources[i], - "sources[" + i + "] length mismatch: " + - actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", ")); - } - assert.equal(actualMap.sourceRoot, - expectedMap.sourceRoot, - "sourceRoot mismatch: " + - actualMap.sourceRoot + " != " + expectedMap.sourceRoot); - assert.equal(actualMap.mappings, expectedMap.mappings, - "mappings mismatch:\nActual: " + actualMap.mappings + "\nExpected: " + expectedMap.mappings); - if (actualMap.sourcesContent) { - assert.equal(actualMap.sourcesContent.length, - expectedMap.sourcesContent.length, - "sourcesContent length mismatch"); - for (var i = 0; i < actualMap.sourcesContent.length; i++) { - assert.equal(actualMap.sourcesContent[i], - expectedMap.sourcesContent[i], - "sourcesContent[" + i + "] mismatch"); - } - } - } - exports.assertEqualMaps = assertEqualMaps; - -}); diff --git a/node_modules/handlebars/package.json b/node_modules/handlebars/package.json index eb40cde..1e86a2d 100644 --- a/node_modules/handlebars/package.json +++ b/node_modules/handlebars/package.json @@ -1,42 +1,102 @@ { "name": "handlebars", - "description": "Extension of the Mustache logicless template language", - "version": "1.0.12", + "barename": "handlebars", + "version": "3.0.3", + "description": "Handlebars provides the power necessary to let you build semantic templates effectively with no frustration", "homepage": "http://www.handlebarsjs.com/", "keywords": [ - "handlebars mustache template html" + "handlebars", + "mustache", + "template", + "html" ], "repository": { "type": "git", - "url": "git://github.com/wycats/handlebars.js.git" + "url": "git+https://github.com/wycats/handlebars.js.git" }, + "author": { + "name": "Yehuda Katz" + }, + "license": "MIT", "engines": { "node": ">=0.4.7" }, "dependencies": { - "optimist": "~0.3", + "optimist": "^0.6.1", + "source-map": "^0.1.40", + "uglify-js": "~2.3" + }, + "optionalDependencies": { "uglify-js": "~2.3" }, "devDependencies": { + "async": "^0.9.0", + "aws-sdk": "~1.5.0", + "babel-loader": "^5.0.0", + "babel-runtime": "^5.1.10", "benchmark": "~1.0", - "dust": "~0.3", - "jison": "~0.3", - "mocha": "*", - "mustache": "~0.7.2" + "dustjs-linkedin": "^2.0.2", + "eco": "~1.1.0-rc-3", + "grunt": "~0.4.1", + "grunt-babel": "^5.0.0", + "grunt-cli": "~0.1.10", + "grunt-contrib-clean": "0.x", + "grunt-contrib-concat": "0.x", + "grunt-contrib-connect": "0.x", + "grunt-contrib-copy": "0.x", + "grunt-contrib-requirejs": "0.x", + "grunt-contrib-uglify": "0.x", + "grunt-contrib-watch": "0.x", + "grunt-eslint": "^11.0.0", + "grunt-saucelabs": "8.x", + "grunt-webpack": "^1.0.8", + "istanbul": "^0.3.0", + "jison": "~0.3.0", + "keen.io": "0.0.3", + "mocha": "~1.20.0", + "mustache": "0.x", + "semver": "^4.0.0", + "underscore": "^1.5.1" }, - "main": "lib/handlebars.js", + "main": "lib/index.js", "bin": { "handlebars": "bin/handlebars" }, "scripts": { - "test": "mocha -u qunit spec/qunit_spec.js" + "test": "grunt" + }, + "jspm": { + "main": "handlebars", + "directories": { + "lib": "dist/amd" + }, + "buildConfig": { + "minify": true + } }, - "optionalDependencies": {}, - "readme": "[![Build Status](https://travis-ci.org/wycats/handlebars.js.png?branch=master)](https://travis-ci.org/wycats/handlebars.js)\n\nHandlebars.js\n=============\n\nHandlebars.js is an extension to the [Mustache templating\nlanguage](http://mustache.github.com/) created by Chris Wanstrath.\nHandlebars.js and Mustache are both logicless templating languages that\nkeep the view and the code separated like we all know they should be.\n\nCheckout the official Handlebars docs site at\n[http://www.handlebarsjs.com](http://www.handlebarsjs.com).\n\n\nInstalling\n----------\nInstalling Handlebars is easy. Simply download the package [from the\nofficial site](http://handlebarsjs.com/) and add it to your web pages\n(you should usually use the most recent version).\n\nUsage\n-----\nIn general, the syntax of Handlebars.js templates is a superset\nof Mustache templates. For basic syntax, check out the [Mustache\nmanpage](http://mustache.github.com/mustache.5.html).\n\nOnce you have a template, use the `Handlebars.compile` method to compile\nthe template into a function. The generated function takes a context\nargument, which will be used to render the template.\n\n```js\nvar source = \"

Hello, my name is {{name}}. I am from {{hometown}}. I have \" +\n \"{{kids.length}} kids:

\" +\n \"
    {{#kids}}
  • {{name}} is {{age}}
  • {{/kids}}
\";\nvar template = Handlebars.compile(source);\n\nvar data = { \"name\": \"Alan\", \"hometown\": \"Somewhere, TX\",\n \"kids\": [{\"name\": \"Jimmy\", \"age\": \"12\"}, {\"name\": \"Sally\", \"age\": \"4\"}]};\nvar result = template(data);\n\n// Would render:\n//

Hello, my name is Alan. I am from Somewhere, TX. I have 2 kids:

\n//
    \n//
  • Jimmy is 12
  • \n//
  • Sally is 4
  • \n//
\n```\n\n\nRegistering Helpers\n-------------------\n\nYou can register helpers that Handlebars will use when evaluating your\ntemplate. Here's an example, which assumes that your objects have a URL\nembedded in them, as well as the text for a link:\n\n```js\nHandlebars.registerHelper('link_to', function() {\n return \"
\" + this.body + \"\";\n});\n\nvar context = { posts: [{url: \"/hello-world\", body: \"Hello World!\"}] };\nvar source = \"
    {{#posts}}
  • {{{link_to}}}
  • {{/posts}}
\"\n\nvar template = Handlebars.compile(source);\ntemplate(context);\n\n// Would render:\n//\n// \n```\n\nHelpers take precedence over fields defined on the context. To access a field\nthat is masked by a helper, a path reference may be used. In the example above\na field named `link_to` on the `context` object would be referenced using:\n\n```\n{{./link_to}}\n```\n\nEscaping\n--------\n\nBy default, the `{{expression}}` syntax will escape its contents. This\nhelps to protect you against accidental XSS problems caused by malicious\ndata passed from the server as JSON.\n\nTo explicitly *not* escape the contents, use the triple-mustache\n(`{{{}}}`). You have seen this used in the above example.\n\n\nDifferences Between Handlebars.js and Mustache\n----------------------------------------------\nHandlebars.js adds a couple of additional features to make writing\ntemplates easier and also changes a tiny detail of how partials work.\n\n### Paths\n\nHandlebars.js supports an extended expression syntax that we call paths.\nPaths are made up of typical expressions and . characters. Expressions\nallow you to not only display data from the current context, but to\ndisplay data from contexts that are descendants and ancestors of the\ncurrent context.\n\nTo display data from descendant contexts, use the `.` character. So, for\nexample, if your data were structured like:\n\n```js\nvar data = {\"person\": { \"name\": \"Alan\" }, company: {\"name\": \"Rad, Inc.\" } };\n```\n\nYou could display the person's name from the top-level context with the\nfollowing expression:\n\n```\n{{person.name}}\n```\n\nYou can backtrack using `../`. For example, if you've already traversed\ninto the person object you could still display the company's name with\nan expression like `{{../company.name}}`, so:\n\n```\n{{#person}}{{name}} - {{../company.name}}{{/person}}\n```\n\nwould render:\n\n```\nAlan - Rad, Inc.\n```\n\n### Strings\n\nWhen calling a helper, you can pass paths or Strings as parameters. For\ninstance:\n\n```js\nHandlebars.registerHelper('link_to', function(title, options) {\n return \"\" + title + \"!\"\n});\n\nvar context = { posts: [{url: \"/hello-world\", body: \"Hello World!\"}] };\nvar source = '
    {{#posts}}
  • {{{link_to \"Post\"}}}
  • {{/posts}}
'\n\nvar template = Handlebars.compile(source);\ntemplate(context);\n\n// Would render:\n//\n// \n```\n\nWhen you pass a String as a parameter to a helper, the literal String\ngets passed to the helper function.\n\n\n### Block Helpers\n\nHandlebars.js also adds the ability to define block helpers. Block\nhelpers are functions that can be called from anywhere in the template.\nHere's an example:\n\n```js\nvar source = \"
    {{#people}}
  • {{#link}}{{name}}{{/link}}
  • {{/people}}
\";\nHandlebars.registerHelper('link', function(options) {\n return '' + options.fn(this) + '';\n});\nvar template = Handlebars.compile(source);\n\nvar data = { \"people\": [\n { \"name\": \"Alan\", \"id\": 1 },\n { \"name\": \"Yehuda\", \"id\": 2 }\n ]};\ntemplate(data);\n\n// Should render:\n// \n```\n\nWhenever the block helper is called it is given one or more parameters,\nany arguments that are passed in the helper in the call and an `options`\nobject containing the `fn` function which executes the block's child.\nThe block's current context may be accessed through `this`.\n\nBlock helpers have the same syntax as mustache sections but should not be\nconfused with one another. Sections are akin to an implicit `each` or\n`with` statement depending on the input data and helpers are explicit\npieces of code that are free to implement whatever behavior they like.\nThe [mustache spec](http://mustache.github.io/mustache.5.html)\ndefines the exact behavior of sections. In the case of name conflicts,\nhelpers are given priority.\n\n### Partials\n\nYou can register additional templates as partials, which will be used by\nHandlebars when it encounters a partial (`{{> partialName}}`). Partials\ncan either be String templates or compiled template functions. Here's an\nexample:\n\n```js\nvar source = \"
    {{#people}}
  • {{> link}}
  • {{/people}}
\";\n\nHandlebars.registerPartial('link', '{{name}}')\nvar template = Handlebars.compile(source);\n\nvar data = { \"people\": [\n { \"name\": \"Alan\", \"id\": 1 },\n { \"name\": \"Yehuda\", \"id\": 2 }\n ]};\n\ntemplate(data);\n\n// Should render:\n// \n```\n\n### Comments\n\nYou can add comments to your templates with the following syntax:\n\n```js\n{{! This is a comment }}\n```\n\nYou can also use real html comments if you want them to end up in the output.\n\n```html\n
\n {{! This comment will not end up in the output }}\n \n
\n```\n\n\nPrecompiling Templates\n----------------------\n\nHandlebars allows templates to be precompiled and included as javascript\ncode rather than the handlebars template allowing for faster startup time.\n\n### Installation\nThe precompiler script may be installed via npm using the `npm install -g handlebars`\ncommand.\n\n### Usage\n\n
\nPrecompile handlebar templates.\nUsage: handlebars template...\n\nOptions:\n  -a, --amd        Create an AMD format function (allows loading with RequireJS)         [boolean]\n  -f, --output     Output File                                                           [string]\n  -k, --known      Known helpers                                                         [string]\n  -o, --knownOnly  Known helpers only                                                    [boolean]\n  -m, --min        Minimize output                                                       [boolean]\n  -s, --simple     Output template function only.                                        [boolean]\n  -r, --root       Template root. Base value that will be stripped from template names.  [string]\n
\n\nIf using the precompiler's normal mode, the resulting templates will be\nstored to the `Handlebars.templates` object using the relative template\nname sans the extension. These templates may be executed in the same\nmanner as templates.\n\nIf using the simple mode the precompiler will generate a single\njavascript method. To execute this method it must be passed to the using\nthe `Handlebars.template` method and the resulting object may be as\nnormal.\n\n### Optimizations\n\n- Rather than using the full _handlebars.js_ library, implementations that\n do not need to compile templates at runtime may include _handlebars.runtime.js_\n whose min+gzip size is approximately 1k.\n- If a helper is known to exist in the target environment they may be defined\n using the `--known name` argument may be used to optimize accesses to these\n helpers for size and speed.\n- When all helpers are known in advance the `--knownOnly` argument may be used\n to optimize all block helper references.\n\nSupported Environments\n----------------------\n\nHandlebars has been designed to work in any ECMAScript 3 environment. This includes\n\n- Node.js\n- Chrome\n- Firefox\n- Safari 5+\n- Opera 11+\n- IE 6+\n\nOlder versions and other runtimes are likely to work but have not been formally\ntested.\n\nPerformance\n-----------\n\nIn a rough performance test, precompiled Handlebars.js templates (in\nthe original version of Handlebars.js) rendered in about half the\ntime of Mustache templates. It would be a shame if it were any other\nway, since they were precompiled, but the difference in architecture\ndoes have some big performance advantages. Justin Marney, a.k.a.\n[gotascii](http://github.com/gotascii), confirmed that with an\n[independent test](http://sorescode.com/2010/09/12/benchmarks.html). The\nrewritten Handlebars (current version) is faster than the old version,\nand we will have some benchmarks in the near future.\n\n\nBuilding\n--------\n\nTo build handlebars, just run `rake release`, and you will get two files\nin the `dist` directory.\n\n\nUpgrading\n---------\n\nSee [release-notes.md](https://github.com/wycats/handlebars.js/blob/master/release-notes.md) for upgrade notes.\n\nKnown Issues\n------------\n* Handlebars.js can be cryptic when there's an error while rendering.\n* Using a variable, helper, or partial named `class` causes errors in IE browsers. (Instead, use `className`)\n\nHandlebars in the Wild\n-----------------\n* [jblotus](http://github.com/jblotus) created [http://tryhandlebarsjs.com](http://tryhandlebarsjs.com)\n for anyone who would like to try out Handlebars.js in their browser.\n* Don Park wrote an Express.js view engine adapter for Handlebars.js called\n [hbs](http://github.com/donpark/hbs).\n* [sammy.js](http://github.com/quirkey/sammy) by Aaron Quint, a.k.a. quirkey,\n supports Handlebars.js as one of its template plugins.\n* [SproutCore](http://www.sproutcore.com) uses Handlebars.js as its main\n templating engine, extending it with automatic data binding support.\n* [Ember.js](http://www.emberjs.com) makes Handlebars.js the primary way to\n structure your views, also with automatic data binding support.\n* Les Hill (@leshill) wrote a Rails Asset Pipeline gem named\n [handlebars_assets](http://github.com/leshill/handlebars_assets).\n* [Gist about Synchronous and asynchronous loading of external handlebars templates](https://gist.github.com/2287070)\n* [Lumbar](walmartlabs.github.io/lumbar) provides easy module-based template management for handlebars projects.\n* [YUI](http://yuilibrary.com/yui/docs/handlebars/) implements a port of handlebars\n\nHave a project using Handlebars? Send us a [pull request](https://github.com/wycats/handlebars.js/pull/new/master)!\n\nHelping Out\n-----------\nTo build Handlebars.js you'll need a few things installed.\n\n* Node.js\n* Ruby\n* therubyracer, for running tests - `gem install therubyracer`\n* rspec, for running tests - `gem install rspec`\n\nThere's a Gemfile in the repo, so you can run `bundle` to install rspec\nand therubyracer if you've got bundler installed.\n\nTo build Handlebars.js from scratch, you'll want to run `rake compile`\nin the root of the project. That will build Handlebars and output the\nresults to the dist/ folder. To run tests, run `rake test`. You can also\nrun our set of benchmarks with `rake bench`. Node tests can be run with\n`npm test` or `rake npm_test`. The default rake target will compile and\nrun both test suites.\n\nSome environments, notably Windows, have issues running therubyracer. Under these\nenvrionments the `rake compile` and `npm test` should be sufficient to test\nmost handlebars functionality.\n\nIf you notice any problems, please report them to the GitHub issue tracker at\n[http://github.com/wycats/handlebars.js/issues](http://github.com/wycats/handlebars.js/issues).\nFeel free to contact commondream or wycats through GitHub with any other\nquestions or feature requests. To submit changes fork the project and\nsend a pull request.\n\nLicense\n-------\nHandlebars.js is released under the MIT license.\n\n", - "readmeFilename": "README.markdown", + "gitHead": "891f48b7e9c321dd9cbe7a898533eb6b2434b8a0", "bugs": { "url": "https://github.com/wycats/handlebars.js/issues" }, - "_id": "handlebars@1.0.12", - "_from": "handlebars@>=1.0.0 <1.1.0" + "_id": "handlebars@3.0.3", + "_shasum": "0e09651a2f0fb3c949160583710d551f92e6d2ad", + "_from": "handlebars@>=3.0.0 <3.1.0", + "_npmVersion": "1.4.28", + "_npmUser": { + "name": "kpdecker", + "email": "kpdecker@gmail.com" + }, + "maintainers": [ + { + "name": "kpdecker", + "email": "kpdecker@gmail.com" + } + ], + "dist": { + "shasum": "0e09651a2f0fb3c949160583710d551f92e6d2ad", + "tarball": "http://registry.npmjs.org/handlebars/-/handlebars-3.0.3.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/handlebars/-/handlebars-3.0.3.tgz", + "readme": "ERROR: No README data found!" } diff --git a/node_modules/handlebars/release-notes.md b/node_modules/handlebars/release-notes.md index 8e67619..21a5346 100644 --- a/node_modules/handlebars/release-notes.md +++ b/node_modules/handlebars/release-notes.md @@ -1,7 +1,286 @@ # Release Notes ## Development -[Commits](https://github.com/wycats/handlebars.js/compare/v1.0.12...master) + +[Commits](https://github.com/wycats/handlebars.js/compare/v3.0.3...master) + +## v3.0.3 - April 28th, 2015 +- [#1004](https://github.com/wycats/handlebars.js/issues/1004) - Latest version breaks with RequireJS (global is undefined) ([@boskee](https://api.github.com/users/boskee)) + +[Commits](https://github.com/wycats/handlebars.js/compare/v3.0.2...v3.0.3) + +## v3.0.2 - April 20th, 2015 +- [#998](https://github.com/wycats/handlebars.js/pull/998) - Add full support for es6 ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#994](https://github.com/wycats/handlebars.js/issues/994) - Access Handlebars.Visitor in browser ([@tamlyn](https://api.github.com/users/tamlyn)) +- [#990](https://github.com/wycats/handlebars.js/issues/990) - Allow passing null/undefined literals subexpressions ([@blimmer](https://api.github.com/users/blimmer)) +- [#989](https://github.com/wycats/handlebars.js/issues/989) - Source-map error with requirejs ([@SteppeEagle](https://api.github.com/users/SteppeEagle)) +- [#967](https://github.com/wycats/handlebars.js/issues/967) - can't access "this" property ([@75lb](https://api.github.com/users/75lb)) +- Use captureStackTrace for error handler - a009a97 +- Ignore branches tested without coverage monitoring - 37a664b + +[Commits](https://github.com/wycats/handlebars.js/compare/v3.0.1...v3.0.2) + +## v3.0.1 - March 24th, 2015 +- [#984](https://github.com/wycats/handlebars.js/pull/984) - Adding documentation for passing arguments into partials ([@johneke](https://api.github.com/users/johneke)) +- [#973](https://github.com/wycats/handlebars.js/issues/973) - version 3 is slower than version 2 ([@elover](https://api.github.com/users/elover)) +- [#966](https://github.com/wycats/handlebars.js/issues/966) - "handlebars --version" does not work with v3.0.0 ([@abloomston](https://api.github.com/users/abloomston)) +- [#964](https://github.com/wycats/handlebars.js/pull/964) - default is a reserved word ([@grassick](https://api.github.com/users/grassick)) +- [#962](https://github.com/wycats/handlebars.js/pull/962) - Add dashbars' link on README. ([@pismute](https://api.github.com/users/pismute)) + +[Commits](https://github.com/wycats/handlebars.js/compare/v3.0.0...v3.0.1) + +## v3.0.0 - February 10th, 2015 +- [#941](https://github.com/wycats/handlebars.js/pull/941) - Add support for dynamic partial names ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#940](https://github.com/wycats/handlebars.js/pull/940) - Add missing reserved words so compiler knows to use array syntax: ([@mattflaschen](https://api.github.com/users/mattflaschen)) +- [#938](https://github.com/wycats/handlebars.js/pull/938) - Fix example using #with helper ([@diwo](https://api.github.com/users/diwo)) +- [#930](https://github.com/wycats/handlebars.js/pull/930) - Add parent tracking and mutation to AST visitors ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#926](https://github.com/wycats/handlebars.js/issues/926) - Depthed lookups fail when program duplicator runs ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#918](https://github.com/wycats/handlebars.js/pull/918) - Add instructions for 'spec/mustache' to CONTRIBUTING.md, fix a few typos ([@oneeman](https://api.github.com/users/oneeman)) +- [#915](https://github.com/wycats/handlebars.js/pull/915) - Ast update ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#910](https://github.com/wycats/handlebars.js/issues/910) - Different behavior of {{@last}} when {{#each}} in {{#each}} ([@zordius](https://api.github.com/users/zordius)) +- [#907](https://github.com/wycats/handlebars.js/issues/907) - Implement named helper variable references ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#906](https://github.com/wycats/handlebars.js/pull/906) - Add parser support for block params ([@mmun](https://api.github.com/users/mmun)) +- [#903](https://github.com/wycats/handlebars.js/issues/903) - Only provide aliases for multiple use calls ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#902](https://github.com/wycats/handlebars.js/pull/902) - Generate Source Maps ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#901](https://github.com/wycats/handlebars.js/issues/901) - Still escapes with noEscape enabled on isolated Handlebars environment ([@zedknight](https://api.github.com/users/zedknight)) +- [#896](https://github.com/wycats/handlebars.js/pull/896) - Simplify BlockNode by removing intermediate MustacheNode ([@mmun](https://api.github.com/users/mmun)) +- [#892](https://github.com/wycats/handlebars.js/pull/892) - Implement parser for else chaining of helpers ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#889](https://github.com/wycats/handlebars.js/issues/889) - Consider extensible parser API ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#887](https://github.com/wycats/handlebars.js/issues/887) - Handlebars.noConflict() option? ([@bradvogel](https://api.github.com/users/bradvogel)) +- [#886](https://github.com/wycats/handlebars.js/issues/886) - Add SafeString to context (or use duck-typing) ([@dominicbarnes](https://api.github.com/users/dominicbarnes)) +- [#870](https://github.com/wycats/handlebars.js/pull/870) - Registering undefined partial throws exception. ([@max-b](https://api.github.com/users/max-b)) +- [#866](https://github.com/wycats/handlebars.js/issues/866) - comments don't respect whitespace control ([@75lb](https://api.github.com/users/75lb)) +- [#863](https://github.com/wycats/handlebars.js/pull/863) - + jsDelivr CDN info ([@tomByrer](https://api.github.com/users/tomByrer)) +- [#858](https://github.com/wycats/handlebars.js/issues/858) - Disable new default auto-indent at included partials ([@majodev](https://api.github.com/users/majodev)) +- [#856](https://github.com/wycats/handlebars.js/pull/856) - jspm compatibility ([@MajorBreakfast](https://api.github.com/users/MajorBreakfast)) +- [#805](https://github.com/wycats/handlebars.js/issues/805) - Request: "strict" lookups ([@nzakas](https://api.github.com/users/nzakas)) + +- Export the default object for handlebars/runtime - 5594416 +- Lookup partials when undefined - 617dd57 + +Compatibility notes: +- Runtime breaking changes. Must match 3.x runtime and precompiler. +- The AST has been upgraded to a public API. + - There are a number of changes to this, but the format is now documented in docs/compiler-api.md + - The Visitor API has been expanded to support mutation and provide a base implementation +- The `JavaScriptCompiler` APIs have been formalized and documented. As part of the sourcemap handling these should be updated to return arrays for concatenation. +- `JavaScriptCompiler.namespace` has been removed as it was unused. +- `SafeString` is now duck typed on `toHTML` + +New Features: +- noConflict +- Source Maps +- Block Params +- Strict Mode +- @last and other each changes +- Chained else blocks +- @data methods can now have helper parameters passed to them +- Dynamic partials + +[Commits](https://github.com/wycats/handlebars.js/compare/v2.0.0...v3.0.0) + +## v2.0.0 - September 1st, 2014 +- Update jsfiddle to 2.0.0-beta.1 - 0670f65 +- Add contrib note regarding handlebarsjs.com docs - 4d17e3c +- Play nice with gemspec version numbers - 64d5481 + +[Commits](https://github.com/wycats/handlebars.js/compare/v2.0.0-beta.1...v2.0.0) + +## v2.0.0-beta.1 - August 26th, 2014 +- [#787](https://github.com/wycats/handlebars.js/pull/787) - Remove whitespace surrounding standalone statements ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#827](https://github.com/wycats/handlebars.js/issues/827) - Render false literal as “false” ([@scoot557](https://api.github.com/users/scoot557)) +- [#767](https://github.com/wycats/handlebars.js/issues/767) - Subexpressions bug with hash and context ([@evensoul](https://api.github.com/users/evensoul)) +- Changes to 0/undefined handling + - [#731](https://github.com/wycats/handlebars.js/pull/731) - Strange behavior for {{#foo}} {{bar}} {{/foo}} when foo is 0 ([@kpdecker](https://api.github.com/users/kpdecker)) + - [#820](https://github.com/wycats/handlebars.js/issues/820) - strange behavior for {{foo.bar}} when foo is 0 or null or false ([@zordius](https://api.github.com/users/zordius)) + - [#837](https://github.com/wycats/handlebars.js/issues/837) - Strange input for custom helper ( foo.bar == false when foo is undefined ) ([@zordius](https://api.github.com/users/zordius)) +- [#819](https://github.com/wycats/handlebars.js/pull/819) - Implement recursive field lookup ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#764](https://github.com/wycats/handlebars.js/issues/764) - This reference not working for helpers ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#773](https://github.com/wycats/handlebars.js/issues/773) - Implicit parameters in {{#each}} introduces a peculiarity in helpers calling convention ([@Bertrand](https://api.github.com/users/Bertrand)) +- [#783](https://github.com/wycats/handlebars.js/issues/783) - helperMissing and consistency for different expression types ([@ErisDS](https://api.github.com/users/ErisDS)) +- [#795](https://github.com/wycats/handlebars.js/pull/795) - Turn the precompile script into a wrapper around a module. ([@jwietelmann](https://api.github.com/users/jwietelmann)) +- [#823](https://github.com/wycats/handlebars.js/pull/823) - Support inverse sections on the with helper ([@dan-manges](https://api.github.com/users/dan-manges)) +- [#834](https://github.com/wycats/handlebars.js/pull/834) - Refactor blocks, programs and inverses ([@mmun](https://api.github.com/users/mmun)) +- [#852](https://github.com/wycats/handlebars.js/issues/852) - {{foo~}} space control behavior is different from older version ([@zordius](https://api.github.com/users/zordius)) +- [#835](https://github.com/wycats/handlebars.js/issues/835) - Templates overwritten if file is loaded twice + +- Expose escapeExpression on the root object - 980c38c +- Remove nested function eval in blockHelperMissing - 6f22ec1 +- Fix compiler program de-duping - 9e3f824 + +Compatibility notes: +- The default build now outputs a generic UMD wrapper. This should be transparent change but may cause issues in some environments. +- Runtime compatibility breaks in both directions. Ensure that both compiler and client are upgraded to 2.0.0-beta.1 or higher at the same time. + - `programWithDepth` has been removed an instead an array of context values is passed to fields needing depth lookups. +- `false` values are now printed to output rather than silently dropped +- Lines containing only block statements and whitespace are now removed. This matches the Mustache spec but may cause issues with code that expects whitespace to exist but would not otherwise. +- Partials that are standalone will now indent their rendered content +- `AST.ProgramNode`'s signature has changed. +- Numerious methods/features removed from psuedo-API classes + - `JavaScriptCompiler.register` + - `JavaScriptCompiler.replaceStack` no longer supports non-inline replace + - `Compiler.disassemble` + - `DECLARE` opcode + - `strip` opcode + - `lookup` opcode + - Content nodes may have their `string` values mutated over time. `original` field provides the unmodified value. +- Removed unused `Handlebars.registerHelper` `inverse` parameter +- `each` helper requires iterator parameter + +[Commits](https://github.com/wycats/handlebars.js/compare/v2.0.0-alpha.4...v2.0.0-beta.1) + +## v2.0.0-alpha.4 - May 19th, 2014 +- Expose setup wrappers for compiled templates - 3638874 + +[Commits](https://github.com/wycats/handlebars.js/compare/v2.0.0-alpha.3...v2.0.0-alpha.4) + +## v2.0.0-alpha.3 - May 19th, 2014 +- [#797](https://github.com/wycats/handlebars.js/pull/797) - Pass full helper ID to helperMissing when options are provided ([@tomdale](https://api.github.com/users/tomdale)) +- [#793](https://github.com/wycats/handlebars.js/pull/793) - Ensure isHelper is coerced to a boolean ([@mmun](https://api.github.com/users/mmun)) +- Refactor template init logic - 085e5e1 + +[Commits](https://github.com/wycats/handlebars.js/compare/v2.0.0-alpha.2...v2.0.0-alpha.3) + +## v2.0.0-alpha.2 - March 6th, 2014 +- [#756](https://github.com/wycats/handlebars.js/pull/756) - fix bug in IE<=8 (no Array::map), closes #751 ([@jenseng](https://api.github.com/users/jenseng)) +- [#749](https://github.com/wycats/handlebars.js/pull/749) - properly handle multiple subexpressions in the same hash, fixes #748 ([@jenseng](https://api.github.com/users/jenseng)) +- [#743](https://github.com/wycats/handlebars.js/issues/743) - subexpression confusion/problem? ([@waynedpj](https://api.github.com/users/waynedpj)) +- [#746](https://github.com/wycats/handlebars.js/issues/746) - [CLI] support `handlebars --version` ([@apfelbox](https://api.github.com/users/apfelbox)) +- [#747](https://github.com/wycats/handlebars.js/pull/747) - updated grunt-saucelabs, failing tests revealed ([@Jonahss](https://api.github.com/users/Jonahss)) +- Make JSON a requirement for the compiler. - 058c0fb +- Temporarily kill the AWS publish CI step - 8347ee2 + +Compatibility notes: +- A JSON polyfill is required to run the compiler under IE8 and below. It's recommended that the precompiler be used in lieu of running the compiler on these legacy environments. + +[Commits](https://github.com/wycats/handlebars.js/compare/v2.0.0-alpha.1...v2.0.0-alpha.2) + +## v2.0.0-alpha.1 - February 10th, 2014 +- [#182](https://github.com/wycats/handlebars.js/pull/182) - Allow passing hash parameters to partials ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#392](https://github.com/wycats/handlebars.js/pull/392) - Access to root context in partials and helpers ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#472](https://github.com/wycats/handlebars.js/issues/472) - Helpers cannot have decimal parameters ([@kayleg](https://api.github.com/users/kayleg)) +- [#569](https://github.com/wycats/handlebars.js/pull/569) - Unable to lookup array values using @index ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#491](https://github.com/wycats/handlebars.js/pull/491) - For nested helpers: get the @ variables of the outer helper from the inner one ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#669](https://github.com/wycats/handlebars.js/issues/669) - Ability to unregister a helper ([@dbachrach](https://api.github.com/users/dbachrach)) +- [#730](https://github.com/wycats/handlebars.js/pull/730) - Raw block helpers ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#634](https://github.com/wycats/handlebars.js/pull/634) - It would be great to have the helper name passed to `blockHelperMissing` ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#729](https://github.com/wycats/handlebars.js/pull/729) - Convert template spec to object literal ([@kpdecker](https://api.github.com/users/kpdecker)) + +- [#658](https://github.com/wycats/handlebars.js/issues/658) - Depthed helpers do not work after an upgrade from 1.0.0 ([@xibxor](https://api.github.com/users/xibxor)) +- [#671](https://github.com/wycats/handlebars.js/issues/671) - Crashes on no-parameter {{#each}} ([@stepancheg](https://api.github.com/users/stepancheg)) +- [#689](https://github.com/wycats/handlebars.js/issues/689) - broken template precompilation ([@AAS](https://api.github.com/users/AAS)) +- [#698](https://github.com/wycats/handlebars.js/pull/698) - Fix parser generation under windows ([@osiris43](https://api.github.com/users/osiris43)) +- [#699](https://github.com/wycats/handlebars.js/issues/699) - @DATA not compiles to invalid JS in stringParams mode ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#705](https://github.com/wycats/handlebars.js/issues/705) - 1.3.0 can not be wrapped in an IIFE ([@craigteegarden](https://api.github.com/users/craigteegarden)) +- [#706](https://github.com/wycats/handlebars.js/pull/706) - README: Use with helper instead of relying on blockHelperMissing ([@scottgonzalez](https://api.github.com/users/scottgonzalez)) + +- [#700](https://github.com/wycats/handlebars.js/pull/700) - Remove redundant conditions ([@blakeembrey](https://api.github.com/users/blakeembrey)) +- [#704](https://github.com/wycats/handlebars.js/pull/704) - JavaScript Compiler Cleanup ([@blakeembrey](https://api.github.com/users/blakeembrey)) + +Compatibility notes: +- `helperMissing` helper no longer has the indexed name argument. Helper name is now available via `options.name`. +- Precompiler output has changed, which breaks compatibility with prior versions of the runtime and precompiled output. +- `JavaScriptCompiler.compilerInfo` now returns generic objects rather than javascript source. +- AST changes + - INTEGER -> NUMBER + - Additional PartialNode hash parameter + - New RawBlockNode type +- Data frames now have a `_parent` field. This is internal but is enumerable for performance/compatability reasons. + +[Commits](https://github.com/wycats/handlebars.js/compare/v1.3.0...v2.0.0-alpha.1) + +## v1.3.0 - January 1st, 2014 +- [#690](https://github.com/wycats/handlebars.js/pull/690) - Added support for subexpressions ([@machty](https://api.github.com/users/machty)) +- [#696](https://github.com/wycats/handlebars.js/pull/696) - Fix for reserved keyword "default" ([@nateirwin](https://api.github.com/users/nateirwin)) +- [#692](https://github.com/wycats/handlebars.js/pull/692) - add line numbers to nodes when parsing ([@fivetanley](https://api.github.com/users/fivetanley)) +- [#695](https://github.com/wycats/handlebars.js/pull/695) - Pull options out from param setup to allow easier extension ([@blakeembrey](https://api.github.com/users/blakeembrey)) +- [#694](https://github.com/wycats/handlebars.js/pull/694) - Make the environment reusable ([@blakeembrey](https://api.github.com/users/blakeembrey)) +- [#636](https://github.com/wycats/handlebars.js/issues/636) - Print line and column of errors ([@sgronblo](https://api.github.com/users/sgronblo)) +- Use literal for data lookup - c1a93d3 +- Add stack handling sanity checks - cd885bf +- Fix stack id "leak" on replaceStack - ddfe457 +- Fix incorrect stack pop when replacing literals - f4d337d + +[Commits](https://github.com/wycats/handlebars.js/compare/v1.2.1...v1.3.0) + +## v1.2.1 - December 26th, 2013 +- [#684](https://github.com/wycats/handlebars.js/pull/684) - Allow any number of trailing characters for valid JavaScript variable ([@blakeembrey](https://api.github.com/users/blakeembrey)) +- [#686](https://github.com/wycats/handlebars.js/pull/686) - Falsy AMD module names in version 1.2.0 ([@kpdecker](https://api.github.com/users/kpdecker)) + +[Commits](https://github.com/wycats/handlebars.js/compare/v1.2.0...v1.2.1) + +## v1.2.0 - December 23rd, 2013 +- [#675](https://github.com/wycats/handlebars.js/issues/675) - Cannot compile empty template for partial ([@erwinw](https://api.github.com/users/erwinw)) +- [#677](https://github.com/wycats/handlebars.js/issues/677) - Triple brace statements fail under IE ([@hamzaCM](https://api.github.com/users/hamzaCM)) +- [#655](https://github.com/wycats/handlebars.js/issues/655) - Loading Handlebars using bower ([@niki4810](https://api.github.com/users/niki4810)) +- [#657](https://github.com/wycats/handlebars.js/pull/657) - Fixes issue where cli compiles non handlebars templates ([@chrishoage](https://api.github.com/users/chrishoage)) +- [#681](https://github.com/wycats/handlebars.js/pull/681) - Adds in-browser testing and Saucelabs CI ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#661](https://github.com/wycats/handlebars.js/pull/661) - Add @first and @index to #each object iteration ([@cgp](https://api.github.com/users/cgp)) +- [#650](https://github.com/wycats/handlebars.js/pull/650) - Handlebars is MIT-licensed ([@thomasboyt](https://api.github.com/users/thomasboyt)) +- [#641](https://github.com/wycats/handlebars.js/pull/641) - Document ember testing process ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#662](https://github.com/wycats/handlebars.js/issues/662) - handlebars-source 1.1.2 is missing from RubyGems. +- [#656](https://github.com/wycats/handlebars.js/issues/656) - Expose COMPILER_REVISION checks as a hook ([@machty](https://api.github.com/users/machty)) +- [#668](https://github.com/wycats/handlebars.js/issues/668) - Consider publishing handlebars-runtime as a separate module on npm ([@dlmanning](https://api.github.com/users/dlmanning)) +- [#679](https://github.com/wycats/handlebars.js/issues/679) - Unable to override invokePartial ([@mattbrailsford](https://api.github.com/users/mattbrailsford)) +- [#646](https://github.com/wycats/handlebars.js/pull/646) - Fix "\\{{" immediately following "\{{" ([@dmarcotte](https://api.github.com/users/dmarcotte)) +- Allow extend to work with non-prototyped objects - eb53f2e +- Add JavascriptCompiler public API tests - 1a751b2 +- Add AST test coverage for more complex paths - ddea5be +- Fix handling of boolean escape in MustacheNode - b4968bb + +Compatibility notes: +- `@index` and `@first` are now supported for `each` iteration on objects +- `Handlebars.VM.checkRevision` and `Handlebars.JavaScriptCompiler.prototype.compilerInfo` now available to modify the version checking behavior. +- Browserify users may link to the runtime library via `require('handlebars/runtime')` + +[Commits](https://github.com/wycats/handlebars.js/compare/v1.1.2...v1.2.0) + +## v1.1.2 - November 5th, 2013 + +- [#645](https://github.com/wycats/handlebars.js/issues/645) - 1.1.1 fails under IE8 ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#644](https://github.com/wycats/handlebars.js/issues/644) - Using precompiled templates (AMD mode) with handlebars.runtime 1.1.1 ([@fddima](https://api.github.com/users/fddima)) + +- Add simple binary utility tests - 96a45a4 +- Fix empty string compilation - eea708a + +[Commits](https://github.com/wycats/handlebars.js/compare/v1.1.1...v1.1.2) + +## v1.1.1 - November 4th, 2013 + +- [#642](https://github.com/wycats/handlebars.js/issues/642) - handlebars 1.1.0 are broken with nodejs + +- Fix release notes link - 17ba258 + +[Commits](https://github.com/wycats/handlebars.js/compare/v1.1.0...v1.1.1) + +## v1.1.0 - November 3rd, 2013 + +- [#628](https://github.com/wycats/handlebars.js/pull/628) - Convert code to ES6 modules ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#336](https://github.com/wycats/handlebars.js/pull/336) - Add whitespace control syntax ([@kpdecker](https://api.github.com/users/kpdecker)) +- [#535](https://github.com/wycats/handlebars.js/pull/535) - Fix for probable JIT error under Safari ([@sorentwo](https://api.github.com/users/sorentwo)) +- [#483](https://github.com/wycats/handlebars.js/issues/483) - Add first and last @ vars to each helper ([@denniskuczynski](https://api.github.com/users/denniskuczynski)) +- [#557](https://github.com/wycats/handlebars.js/pull/557) - `\\{{foo}}` escaping only works in some situations ([@dmarcotte](https://api.github.com/users/dmarcotte)) +- [#552](https://github.com/wycats/handlebars.js/pull/552) - Added BOM removal flag. ([@blessenm](https://api.github.com/users/blessenm)) +- [#543](https://github.com/wycats/handlebars.js/pull/543) - publish passing master builds to s3 ([@fivetanley](https://api.github.com/users/fivetanley)) + +- [#608](https://github.com/wycats/handlebars.js/issues/608) - Add `includeZero` flag to `if` conditional +- [#498](https://github.com/wycats/handlebars.js/issues/498) - `Handlebars.compile` fails on empty string although a single blank works fine +- [#599](https://github.com/wycats/handlebars.js/issues/599) - lambda helpers only receive options if used with arguments +- [#592](https://github.com/wycats/handlebars.js/issues/592) - Optimize array and subprogram performance +- [#571](https://github.com/wycats/handlebars.js/issues/571) - uglify upgrade breaks compatibility with older versions of node +- [#587](https://github.com/wycats/handlebars.js/issues/587) - Partial inside partial breaks? + + +Compatibility notes: +- The project now includes separate artifacts for AMD, CommonJS, and global objects. + - AMD: Users may load the bundled `handlebars.amd.js` or `handlebars.runtime.amd.js` files or load individual modules directly. AMD users should also note that the handlebars object is exposed via the `default` field on the imported object. This [gist](https://gist.github.com/wycats/7417be0dc361a69d5916) provides some discussion of possible compatibility shims. + - CommonJS/Node: Node loading occurs as normal via `require` + - Globals: The `handlebars.js` and `handlebars.runtime.js` files should behave in the same manner as the v1.0.12 / 1.0.0 release. +- Build artifacts have been removed from the repository. [npm][npm], [components/handlebars.js][components], [cdnjs][cdnjs], or the [builds page][builds-page] should now be used as the source of built artifacts. +- Context-stored helpers are now always passed the `options` hash. Previously no-argument helpers did not have this argument. + + +[Commits](https://github.com/wycats/handlebars.js/compare/v1.0.12...v1.1.0) ## v1.0.12 / 1.0.0 - May 31 2013 @@ -21,6 +300,7 @@ Compatibility notes: - The parser is now stricter on `{{{`, requiring that the end token be `}}}`. Templates that do not follow this convention should add the additional brace value. - Code that relies on global the namespace being muted when custom helpers or partials are passed will need to explicitly pass an `undefined` value for any helpers that should not be available. +- The compiler version has changed. Precompiled templates with 1.0.12 or higher must use the 1.0.0 or higher runtime. [Commits](https://github.com/wycats/handlebars.js/compare/v1.0.11...v1.0.12) @@ -91,3 +371,8 @@ Use: ```js template(context, {helpers: helpers, partials: partials, data: data}) ``` + +[builds-page]: http://builds.handlebarsjs.com.s3.amazonaws.com/index.html +[cdnjs]: http://cdnjs.com/libraries/handlebars.js/ +[components]: https://github.com/components/handlebars.js +[npm]: https://npmjs.org/package/handlebars diff --git a/node_modules/handlebars/test.js b/node_modules/handlebars/test.js deleted file mode 100644 index 0a6dde5..0000000 --- a/node_modules/handlebars/test.js +++ /dev/null @@ -1,20 +0,0 @@ -var Handlebars = require('./lib/handlebars'); - -var succeedingTemplate = '{{#inverse}} {{#blk}} Unexpected {{/blk}} {{else}} {{#blk}} Expected {{/blk}} {{/inverse}}'; -var failingTemplate = '{{#inverse}} {{#blk}} Unexpected {{/blk}} {{else}} {{#blk}} Expected {{/blk}} {{/inverse}}'; - -console.log(Handlebars.precompile(failingTemplate)); - -var helpers = { - blk: function(block) { return block.fn(''); }, - inverse: function(block) { return block.inverse(''); } -}; - -function output(template_string) { - var compiled = Handlebars.compile(template_string); - var out = compiled({}, {helpers: helpers}); - console.log(out); -} - - -output(failingTemplate); // output: Unexpected diff --git a/node_modules/hapi/.gitattributes b/node_modules/hapi/.gitattributes deleted file mode 100644 index 399a243..0000000 --- a/node_modules/hapi/.gitattributes +++ /dev/null @@ -1,10 +0,0 @@ -# Set default behaviour, in case users don't have core.autocrlf set. -* text eol=lf - -# Explicitly declare text files we want to always be normalized and converted -# to native line endings on checkout. -*.js text eol=lf - -# Denote all files that are truly binary and should not be modified. -*.png binary -*.jpg binary \ No newline at end of file diff --git a/node_modules/hapi/.npmignore b/node_modules/hapi/.npmignore index 7e1574d..c67999d 100644 --- a/node_modules/hapi/.npmignore +++ b/node_modules/hapi/.npmignore @@ -5,7 +5,6 @@ dump.rdb node_modules results.tap results.xml -npm-shrinkwrap.json config.json .DS_Store */.DS_Store @@ -14,5 +13,4 @@ config.json */._* */*/._* coverage.* -lib-cov -complexity.md +.settings diff --git a/node_modules/hapi/.travis.yml b/node_modules/hapi/.travis.yml index 941e14e..f502178 100755 --- a/node_modules/hapi/.travis.yml +++ b/node_modules/hapi/.travis.yml @@ -2,9 +2,5 @@ language: node_js node_js: - 0.10 - -notifications: - irc: - channels: - - "irc.freenode.net#hapi" - skip_join: true + - 0.12 + - iojs diff --git a/node_modules/hapi/CONTRIBUTING.md b/node_modules/hapi/CONTRIBUTING.md index 45ef48b..529d316 100755 --- a/node_modules/hapi/CONTRIBUTING.md +++ b/node_modules/hapi/CONTRIBUTING.md @@ -2,13 +2,13 @@ We welcome contributions from the community and are pleased to have them. Please follow this guide when logging issues or making code changes. ## Logging Issues -All issues should be created using the [new issue form](https://github.com/spumko/hapi/issues/new). Clearly describe the issue including steps to reproduce if there are any. Also, make sure to indicate the earliest version that has the issue being reported. +All issues should be created using the [new issue form](https://github.com/hapijs/hapi/issues/new). Clearly describe the issue including steps to reproduce if there are any. Also, make sure to indicate the earliest version that has the issue being reported. ## Patching Code Code changes are welcome and should follow the guidelines below. * Fork the repository on GitHub. -* Fix the issue ensuring that your code follows the [style guide](https://github.com/spumko/hapi/blob/master/docs/Style.md). +* Fix the issue ensuring that your code follows the [style guide](https://github.com/hapijs/contrib/blob/master/Style.md). * Add tests for your new code ensuring that you have 100% code coverage (we can help you reach 100% but will not merge without it). * Run `make test-cov-html` to generate a report of test coverage -* [Pull requests](http://help.github.com/send-pull-requests/) should be made to the [master branch](https://github.com/spumko/hapi/tree/master). +* [Pull requests](http://help.github.com/send-pull-requests/) should be made to the [master branch](https://github.com/hapijs/hapi/tree/master). diff --git a/node_modules/hapi/LICENSE b/node_modules/hapi/LICENSE index 87c1f4e..5530904 100755 --- a/node_modules/hapi/LICENSE +++ b/node_modules/hapi/LICENSE @@ -1,4 +1,5 @@ -Copyright (c) 2011-2013, Walmart. +Copyright (c) 2011-2014, Walmart and other contributors. +Copyright (c) 2011, Yahoo Inc. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -8,14 +9,14 @@ modification, are permitted provided that the following conditions are met: * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Walmart nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + * The names of any contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL WALMART BE LIABLE FOR ANY +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND @@ -23,11 +24,8 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * * * - -Portions of this project were initially based on Postmile, Copyright (c) 2011, Yahoo Inc. -Postmile is published at https://github.com/yahoo/postmile and its licensing terms are -published at https://github.com/yahoo/postmile/blob/master/LICENSE. - +The complete list of contributors can be found at: https://github.com/hapijs/hapi/graphs/contributors +Portions of this project were initially based on the Yahoo! Inc. Postmile project, +published at https://github.com/yahoo/postmile. diff --git a/node_modules/hapi/Makefile b/node_modules/hapi/Makefile deleted file mode 100755 index 6fb1472..0000000 --- a/node_modules/hapi/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -test: - @node node_modules/lab/bin/lab -test-cov: - @node node_modules/lab/bin/lab -r threshold -t 100 -test-cov-html: - @node node_modules/lab/bin/lab -r html -o coverage.html - -.PHONY: test test-cov test-cov-html - diff --git a/node_modules/hapi/README.md b/node_modules/hapi/README.md index 85ebd15..78ffbc3 100755 --- a/node_modules/hapi/README.md +++ b/node_modules/hapi/README.md @@ -1,65 +1,15 @@ - - + -A rich framework for building web applications and services. **hapi** is a simple to use configuration-centric -framework with built-in support for input validation, caching, authentication, and other essential facilities. -**hapi** enables developers to focus on writing reusable application logic instead of spending time building -infrastructure. The framework supports a powerful plugin architecture for pain-free and scalable extensibility. +### Web and services application framework -For the latest updates and release information follow [@hapijs](https://twitter.com/hapijs) on twitter. +Lead Maintainer: [Eran Hammer](https://github.com/hueniverse) -Current version: **1.8.x** +**hapi** is a simple to use configuration-centric framework with built-in support for input validation, caching, +authentication, and other essential facilities for building web and services applications. **hapi** enables +developers to focus on writing reusable application in a highly modular and prescriptive approach. -Node version: **0.10** required - -[![Build Status](https://secure.travis-ci.org/spumko/hapi.png)](http://travis-ci.org/spumko/hapi) - - -[![NPM](https://nodei.co/npm/hapi.png?downloads=true&stars=true)](https://nodei.co/npm/hapi/) - -## Getting started - -Start by creating a _package.json_: -``` -npm init -``` - -Install **hapi** and have it saved to your _package.json_ dependencies: -``` -npm install hapi --save -``` - -Create an _'index.js'_ file and with the following contents: -```javascript -var Hapi = require('hapi'); - -// Create a server with a host and port -var server = Hapi.createServer('localhost', 8000); - -// Add the route -server.route({ - method: 'GET', - path: '/hello', - handler: function () { - - this.reply('hello world'); - } -}); - -// Start the server -server.start(); -``` - -Launch the application (`node .`) and open 'http://localhost:8000/hello' in a browser. - - -## More information - -- For the **latest updates** follow [@hapijs](https://twitter.com/hapijs). -- For more **information, tutorials, and references** on the currently published version, visit [**hapijs.com**](http://hapijs.com) -- Information about the **work-in-progress** in the master branch: - - [API reference](/docs/Reference.md) - - [Upcoming breaking changes](https://github.com/spumko/hapi/issues?labels=breaking+changes) -- For **discussions** join the [#hapi channel](http://webchat.freenode.net/?channels=hapi) on irc.freenode.net -- Any **issues or questions** (no matter how basic), open an issue. +Development version: **8.5.x** ([release notes](https://github.com/hapijs/hapi/issues?labels=release+notes&page=1&state=closed)) +[![Build Status](https://secure.travis-ci.org/hapijs/hapi.svg)](http://travis-ci.org/hapijs/hapi) +For the latest updates and release information visit [hapijs.com](http://hapijs.com) and follow [@hapijs](https://twitter.com/hapijs) on twitter. If you have questions, please open an issue in the +[discussion forum](https://github.com/hapijs/discuss). diff --git a/node_modules/hapi/bin/hapi b/node_modules/hapi/bin/hapi deleted file mode 100755 index 0a09db5..0000000 --- a/node_modules/hapi/bin/hapi +++ /dev/null @@ -1,123 +0,0 @@ -#!/usr/bin/env node - -// Load modules - -var Fs = require('fs'); -var Optimist = require('optimist'); -var Hapi = require('../'); - - -// Declare internals - -var internals = {}; - - -internals.argv = Optimist.usage('Usage: $0 -c manifest.json [-p node_modules_path]') - .demand(['c']) - .argv; - - -internals.getManifest = function () { - - var manifest = null; - var manifestPath = internals.argv.c[0] !== '/' ? process.cwd() + '/' + internals.argv.c : internals.argv.c; - - try { - delete require.cache[require.resolve(manifestPath)]; // Delete manifest from cache to ensure we are loading a fresh copy - manifest = require(manifestPath); - } - catch (err) { - console.log('Failed loading configuration file: ' + internals.argv.c + ' (' + err.message + ')'); - process.exit(1); - } - - return manifest; -} - - -internals.loadPacks = function (manifest, callback) { - - if (!internals.argv.p) { - return callback(); - } - - Fs.realpath(internals.argv.p, function (err, path) { - - if (err) { - return callback(err); - } - - var packs = [].concat(manifest); - packs.forEach(function (set) { - - set.pack = set.pack || {}; - set.pack.requirePath = path; - }); - - callback(); - }); -} - - -internals.createComposer = function (manifest) { - - var attached = !!internals.composer; // When composer exists events are already attached - internals.composer = new Hapi.Composer(manifest); - - internals.composer.compose(function (err) { - - Hapi.utils.assert(!err, 'Failed loading plugins: ' + (err && err.message)); - internals.composer.start(function (err) { - - Hapi.utils.assert(!err, 'Failed starting server: ' + (err && err.message)); - - if (!attached) { - internals.attachEvents(); - } - }); - }); -}; - - -internals.attachEvents = function () { - - process.once('SIGQUIT', internals.stop); // Use kill -s QUIT {pid} to kill the servers gracefully - process.on('SIGUSR2', internals.restart); // Use kill -s SIGUSR2 {pid} to restart the servers -}; - - -internals.stop = function () { - - internals.composer.stop(function () { - - process.exit(); - }); -}; - - -internals.restart = function () { - - console.log('Stopping...'); - internals.composer.stop(function () { - - console.log('Starting...'); - internals.start(); - }); -}; - - -internals.start = function () { - - var manifest = internals.getManifest(); - internals.loadPacks(manifest, function (err) { - - if (err) { - console.error(err); - process.exit(); - } - - internals.createComposer(manifest); - }); -}; - -internals.start(); \ No newline at end of file diff --git a/node_modules/hapi/docs/Plugins.md b/node_modules/hapi/docs/Plugins.md deleted file mode 100644 index ed4084c..0000000 --- a/node_modules/hapi/docs/Plugins.md +++ /dev/null @@ -1,18 +0,0 @@ -# Hapi Plugins - -***Create a [pull request](http://help.github.com/send-pull-requests/) to add a plugin to the list.*** - -## Security - -#### [Crumb](https://npmjs.org/package/crumb) - CSRF crumb generation - -#### [Travelogue](https://npmjs.org/package/travelogue) - Passport.js integration helper - -#### [Yar](https://npmjs.org/package/yar) - Cookie jar - - -## Monitoring - -#### [Good](https://npmjs.org/package/good) - Server and process monitoring - -#### [TV](https://npmjs.org/package/tv) - Debug console for request monitoring diff --git a/node_modules/hapi/docs/Reference.md b/node_modules/hapi/docs/Reference.md deleted file mode 100755 index 4c0f89b..0000000 --- a/node_modules/hapi/docs/Reference.md +++ /dev/null @@ -1,3206 +0,0 @@ -# 1.8.x API Reference - -- [`Hapi.Server`](#hapiserver) - - [`new Server([host], [port], [options])`](#new-serverhost-port-options) - - [`createServer([host], [port], [options])`](#createServerhost-port-options) - - [Server options](#server-options) - - [`Server` properties](#server-properties) - - [`Server` methods](#server-methods) - - [`server.start([callback])`](#serverstartcallback) - - [`server.stop([options], [callback])`](#serverstopoptions-callback) - - [`server.route(options)`](#serverrouteoptions) - - [Route options](#route-options) - - [Path processing](#path-processing) - - [Path parameters](#path-parameters) - - [Route handler](#route-handler) - - [Route prerequisites](#route-prerequisites) - - [Route not found](#route-not-found) - - [`server.route(routes)`](#serverrouteroutes) - - [`server.routingTable()`](#serverroutingtable) - - [`server.log(tags, [data, [timestamp]])`](#serverlogtags-data-timestamp) - - [`server.state(name, [options])`](#serverstatename-options) - - [`server.views(options)`](#serverviewsoptions) - - [`server.auth(name, options)`](#serverauthname-options) - - [Basic authentication](#basic-authentication) - - [Cookie authentication](#cookie-authentication) - - [Hawk authentication](#hawk-authentication) - - [Bewit authentication](#bewit-authentication) - - [`server.ext(event, method, [options])`](#serverextevent-method-options) - - [Request lifecycle](#request-lifecycle) - - [`server.helper(name, method, [options])`](#serverhelpername-method-options) - - [`server.inject(options, callback)`](#serverinjectoptions-callback) - - [`Server` events](#server-events) -- [Request object](#request-object) - - [`request` properties](#request-properties) - - [`request` methods](#request-methods) - - [`request.setUrl(url)`](#requestseturlurl) - - [`request.setMethod(method)`](#requestsetmethodmethod) - - [`request.log(tags, [data, [timestamp]])`](#requestlogtags-data-timestamp) - - [`request.getLog([tags])`](#requestgetlogtags) - - [`request.tail([name])`](#requesttailname) - - [`request.setState(name, value, [options])`](#requestsetstatename-value-options) - - [`request.clearState(name)`](#requestclearstatename) - - [`request.reply([result])`](#requestreplyresult) - - [`request.reply.redirect(uri)`](#requestreplyredirecturi) - - [`request.reply.view(template, [context, [options]])`](#requestreplyviewtemplate-context-options) - - [`request.reply.close()`](#requestreplyclose) - - [`request.generateView(template, context, [options])`](#requestgenerateviewtemplate-context-options) - - [`request.response()`](#requestresponse) -- [`Hapi.response`](#hapiresponse) - - [Flow control](#flow-control) - - [Response types](#response-types) - - [`Generic`](#generic) - - [`Empty`](#empty) - - [`Text`](#text) - - [`Buffer`](#buffer) - - [`Stream`](#stream) - - [`Obj`](#obj) - - [`File`](#file) - - [`Redirection`](#redirection) - - [`View`](#view) - - [`Cacheable`](#cacheable) -- [`Hapi.error`](#hapierror) - - [Error transformation](#error-transformation) - - [`badRequest([message])`](#badrequestmessage) - - [`unauthorized(message, [scheme, [attributes]])`](#unauthorizedmessage-scheme-attributes) - - [`unauthorized(message, wwwAuthenticate)`](#unauthorizedmessage-wwwauthenticate) - - [`clientTimeout([message])`](#clienttimeoutmessage) - - [`serverTimeout([message])`](#servertimeoutmessage) - - [`forbidden([message])`](#forbiddenmessage) - - [`notFound([message])`](#notfoundmessage) - - [`internal([message, [data]])`](#internalmessage-data) - - [`passThrough(code, payload, contentType, headers)`](#passthroughcode-payload-contenttype-headers) -- [`Hapi.Pack`](#hapipack) - - [`new Pack([options])`](#new-packoptions) - - [`Pack` properties](#pack-properties) - - [`Pack` methods](#pack-methods) - - [`pack.server([host], [port], [options])`](#packserverhost-port-options) - - [`pack.start([callback])`](#packstartcallback) - - [`pack.stop([options], [callback])`](#packstopoptions-callback) - - [`pack.allow(permissions)`](#packallowpermissions) - - [`pack.require(name, options, callback)`](#packrequirename-options-callback) - - [`pack.require(names, callback)`](#packrequirenames-callback) - - [`pack.register(plugin, options, callback)`](#packregisterplugin-options-callback) -- [`Hapi.Composer`](#hapicomposer) - - [`new Composer(manifest)`](#new-composermanifest) - - [`composer.compose(callback)`](#composercomposecallback) - - [`composer.start([callback])`](#composerstartcallback) - - [`composer.stop([options], [callback])`](#composerstopoptions-callback) -- [Plugin interface](#plugin-interface) - - [`exports.register(plugin, options, next)`](#exportsregisterplugin-options-next) - - [Root methods and properties](#root-methods-and-properties) - - [`plugin.version`](#pluginversion) - - [`plugin.path`](#pluginpath) - - [`plugin.hapi`](#pluginhapi) - - [`plugin.app`](#pluginapp) - - [`plugin.events`](#pluginevents) - - [`plugin.log(tags, [data, [timestamp]])`](#pluginlogtags-data-timestamp) - - [`plugin.dependency(deps)`](#plugindependencydeps) - - [`plugin.views(options)`](#pluginviewsoptions) - - [`plugin.helper(name, method, [options])`](#pluginhelpername-method-options) - - [`plugin.cache(options)`](#plugincacheoptions) - - [Selectable methods and properties](#selectable-methods-and-properties) - - [`plugin.select(labels)`](#pluginselectlabels) - - [`plugin.length`](#pluginlength) - - [`plugin.api(key, value)`](#pluginapikey-value) - - [`plugin.api(obj)`](#pluginapiobj) - - [`plugin.route(options)`](#pluginrouteoptions) - - [`plugin.route(routes)`](#pluginrouteroutes) - - [`plugin.state(name, [options])`](#pluginstatename-options) - - [`plugin.auth(name, options)`](#pluginauthname-options) - - [`plugin.ext(event, method, [options])`](#pluginextevent-method-options) -- [`Hapi.utils`](#hapiutils) - - [`version()`](#version) -- [`Hapi.types`](#hapitypes) -- [`Hapi.state`](#hapistate) - - [`prepareValue(name, value, options, callback)`](#preparevaluename-value-options-callback) - -## `Hapi.Server` - -### `new Server([host], [port], [options])` - -Creates a new server instance with the following arguments: - -- `host` - the hostname or IP address the server is bound to. Defaults to `0.0.0.0` which means any available network - interface. Set to `127.0.0.1` or `localhost` to restrict connection to those coming from the same machine. -- `port` - the TPC port the server is listening to. Defaults to port `80` for HTTP and to `443` when TLS is configured. - to use an ephemeral port, use `0` and once the server is started, retrieve the port allocation via `server.info.port`. -- `options` - An object with the server configuration as described in [server options](#server-options). - -```javascript -var Hapi = require('hapi'); -var server = new Hapi.Server('localhost', 8000, { cors: true }); -``` - -### `createServer([host], [port], [options])` - -An alternative method for creating a server instance using the same arguments as `new Server()`. - -```javascript -var Hapi = require('hapi'); -var server = Hapi.createServer('localhost', 8000, { cors: true }); -``` - -### Server options - -When creating a server instance, the following options configure the server's behavior: - -- `app` - application-specific configuration. Provides a safe place to store application configuration without potential conflicts with **hapi**. - Should not be used by plugins which should use `plugins[name]`. -

-- `auth` - configures one or more authentication strategies. The `auth` key can be set to a single strategy object (the name will default to `'default'`), - or to an object with multiple strategies where the strategy name is the object key. The authentication strategies and their options are described in - [`server.auth()`](#serverauthname-options). -

-- `cache` - determines the type of server-side cache used. Every server includes a cache for storing and reusing request - responses and helper results. By default a simple memory-based cache is used which has very limited capacity and is not suitable for production - environments. In addition to the memory cache, a Redis-based or a MongoDB-based cache can be configured. Actual caching is only utilized if routes, - helpers, and plugins are explicitly configured to store their state in the cache. The server cache configuration only defines the store itself. The - `cache` options are described in the [**catbox** module documentation](https://github.com/spumko/catbox#client). -

-- `cors` - the [Cross-Origin Resource Sharing](http://www.w3.org/TR/cors/) protocol allows browsers to make cross-origin API calls. CORS is - required by web application running inside a browser which are loaded from a different domain than the API server. CORS headers are disabled by - default. To enable, set `cors` to `true`, or to an object with the following options: - - `origin` - a strings array of allowed origin servers ('Access-Control-Allow-Origin'). Defaults to any origin `['*']`. - - `maxAge` - number of seconds the browser should cache the CORS response ('Access-Control-Max-Age'). The greater the value, the longer it - will take before the browser checks for changes in policy. Defaults to `86400` (one day). - - `headers` - a strings array of allowed headers ('Access-Control-Allow-Headers'). Defaults to `['Authorization', 'Content-Type', 'If-None-Match']`. - - `additionalHeaders` - a strings array of additional headers to `headers`. Use this to keep the default headers in place. - - `methods` - a strings array of allowed HTTP methods ('Access-Control-Allow-Methods'). Defaults to `['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'OPTIONS']`. - - `additionalMethods` - a strings array of additional methods to `methods`. Use this to keep the default methods in place. - - `exposedHeaders` - a strings array of exposed headers ('Access-Control-Expose-Headers'). Defaults to `['WWW-Authenticate', 'Server-Authorization']`. - - `additionalExposedHeaders` - a strings array of additional headers to `exposedHeaders`. Use this to keep the default headers in place. - - `credentials` - if `true`, allows user credentials to be sent ('Access-Control-Allow-Credentials'). Defaults to `false`. -

-- `debug` - controls the error types sent to the console: - - `request` - a string array of request log tags to be displayed via `console.error()` when the events are logged via `request.log()`. Defaults - to uncaught errors thrown in external code (these errors are handled automatically and result in an Internal Server Error (500) error response. - For example, to display all errors, change the option to `['error', 'uncaught']`. To turn off all console debug messages set it to `false`. -

-- `files` - defines the behavior for serving static resources using the built-in route handlers for files and directories: - - `relativeTo` - determines how relative paths are resolved. Available values: - - `'cwd'` - relative paths are resolved using the active process path (`process.cwd()`). This is the default setting. - - `'routes'` - relative paths are resolved relative to the source file in which the `server.route()` method is called. This means the - location of the source code determines the location of the static resources when using relative paths. - - an absolute path (e.g. '/path') used as prefix for all relative paths. -

-- `labels` - a string array of labels used when registering plugins to [`plugin.select()`](#pluginselectlabels) matching server labels. Defaults - to an empty array `[]` (no labels). -

-- `location` - used to convert relative 'Location' header URIs to absolute, by adding this value as prefix. Value must not contain a trailing `'/'`. - Defaults to the host received in the request HTTP 'Host' header and if missing, to `server.info.uri`. -

-- `payload` - controls how incoming payloads (request body) are processed: - - `maxBytes` - limits the size of incoming payloads to the specified byte count. Allowing very large payloads may cause the server to run - out of memory. Defaults to `1048576` (1MB). -

-- `plugins` - plugin-specific configuration. Provides a place to store and pass plugin configuration that is at server-level. The `plugins` is - an object where each key is a plugin name and the value is the configuration. -

-- `router` - controls how incoming request URIs are matched against the routing table: - - `isCaseSensitive` - determines whether the paths '/example' and '/EXAMPLE' are considered different resources. Defaults to `true`. - - `normalizeRequestPath` - determines whether request paths should be normalized prior to matching. Normalization percent-encodes reserved - characters, decodes unreserved characters, and capitalizes any percent encoded values. Useful when serving non-compliant HTTP clients. - Defaults to `false`. -

-- `state` - HTTP state management (cookies) allows the server to store information on the client which is sent back to the server with every - request (as defined in [RFC 6265](https://tools.ietf.org/html/rfc6265)). - - `cookies` - The server automatically parses incoming cookies based on these options: - - `parse` - determines if incoming 'Cookie' headers are parsed and stored in the `request.cookies` object. Defaults to `true`. - - `failAction` - determines how to handle cookie parsing errors. Allowed values are: - - `'error'` - return a Bad Request (400) error response. This is the default value. - - `'log'` - report the error but continue processing the request. - - `'ignore'` - take no action. - - `clearInvalid` - if `true`, automatically instruct the client to remove invalid cookies. Defaults to `false`. - - `strictHeader` - if `false`, allows any cookie value including values in violation of [RFC 6265](https://tools.ietf.org/html/rfc6265). Defaults to `true`. -

-- `timeout` - define timeouts for processing durations: - - `server` - response timeout in milliseconds. Sets the maximum time allowed for the server to respond to an incoming client request before giving - up and responding with a Service Unavailable (503) error response. Disabled by default (`false`). - - `client` - request timeout in milliseconds. Sets the maximum time allowed for the client to transmit the request payload (body) before giving up - and responding with a Request Timeout (408) error response. Set to `false` to disable. Defaults to `10000` (10 seconds). - - `socket` - by default, node sockets automatically timeout after 2 minutes. Use this option to override this behavior. Defaults to `undefined` - which leaves the node default unchanged. Set to `false` to disable socket timeouts. -

-- `tls` - used to create an HTTPS server. The `tls` object is passed unchanged as options to the node.js HTTPS server as described in the - [node.js HTTPS documentation](http://nodejs.org/api/https.html#https_https_createserver_options_requestlistener). -

-- `maxSockets` - used to set the number of sockets available per outgoing host connection. Default is null. This impacts all servers sharing the process. -

-- `views` - enables support for view rendering (using templates to generate responses). Disabled by default. - To enable, set to an object with the following options: - - `engines` - (required) an object where each key is a file extension (e.g. 'html', 'jade'), mapped to the npm module name (string) used for - rendering the templates. Alternatively, the extension can be mapped to an object with the following options: - - `module` - the npm module name (string) to require or an object with: - - `compile()` - the rendering function. The required function signature depends on the `compileMode` settings. If the `compileMode` is - `'sync'`, the signature is `compile(template, options)`, the return value is a function with signature `function(context, options)`, - and the method is allowed to throw errors. If the `compileMode` is `'async'`, the signature is `compile(template, options, callback)` - where `callback` has the signature `function(err, compiled)` where `compiled` is a function with signature `function(context, options)`. - - any of the `views` options listed below (except `defaultExtension`) to override the defaults for a specific engine. - - `defaultExtension` - defines the default filename extension to append to template names when multiple engines are configured and not - explicit extension is provided for a given template. No default value. - - `path` - the root file path used to resolve and load the templates identified when calling `request.reply.view()`. Defaults to current working - directory. - - `partialsPath` - the root file path where partials are located. Partials are small segments of template code that can be nested and reused - throughout other templates. Defaults to no partials support (empty path). - - `helpersPath` - the directory path where helpers are located. Helpers are functions used within templates to perform transformations - and other data manipulations using the template context or other inputs. Each '.js' file in the helpers directory is loaded and the file name - is used as the helper name. The files must export a single method with the signature `function(context)` and return a string. Sub-folders are - not supported and are ignored. Defaults to no helpers support (empty path). - - `basePath` - a base path used as prefix for `path` and `partialsPath`. No default. - - `layout` - if set to `true`, layout support is enabled. A layout is a single template file used as the parent template for other view templates - in the same engine. The layout template name must be 'layout.ext' where 'ext' is the engine's extension. Disable 'layout' when using Jade as - it will handle including any layout files independently of Hapi. Defaults to `false`. - - `layoutKeyword` - the key used by the template engine to denote where primary template content should go. Defaults to `'content'`. - - `encoding` - the text encoding used by the templates when reading the files and outputting the result. Defaults to `'utf-8'`. - - `isCached` - if set to `false`, templates will not be cached (thus will be read from file on every use). Defaults to `true`. - - `allowAbsolutePaths` - if set to `true`, allows absolute template paths passed to `request.reply.view()`. Defaults to `false`. - - `allowInsecureAccess` - if set to `true`, allows template paths passed to `request.reply.view()` to contain '../'. Defaults to `false`. - - `compileOptions` - options object passed to the engine's compile function. Defaults to empty options `{}`. - - `runtimeOptions` - options object passed to the returned function from the compile operation. Defaults to empty options `{}`. - - `contentType` - the content type of the engine results. Defaults to `'text/html'`. - - `compileMode` - specify whether the engine `compile()` method is `'sync'` or `'async'`. Defaults to `'sync'`. - -### `Server` properties - -Each instance of the `Server` object have the following properties: - -- `app` - application-specific state. Provides a safe place to store application data without potential conflicts with **hapi**. - Should not be used by plugins which should use `plugins[name]`. -- `helpers` - helper functions registered with [`server.helper()`](#serverhelpername-method-options). -- `info` - server information: - - `port` - the port the server was configured to (before `start()`) or bound to (after `start()`). - - `host` - the hostname the server was configured to (defaults to `'0.0.0.0'` if no host was provided). - - `protocol` - the protocol used (e.g. `'http'` or `'https'`). - - `uri` - a string with the following format: 'protocol://host:port' (e.g. 'http://example.com:8080'). -- `listener` - the node HTTP server object. -- `pack` - the [`Pack`](#hapipack) object the server belongs to (automatically assigned when creating a server instance directly). -- `plugins` - an object where each key is a plugin name and the value is the API registered by that plugin using [`plugin.api()`](#pluginapikey-value). -- `settings` - an object containing the [server options](#server-options) after applying the defaults. - -### `Server` methods - -#### `server.start([callback])` - -Starts the server by listening for incoming connections on the configured port. If provided, `callback()` is called once the server is -ready for new connections. If the server is already started, the `callback()` is called on the next tick. - -```javascript -var Hapi = require('hapi'); -var server = new Hapi.Server(); -server.start(function () { - - console.log('Server started at: ' + server.info.uri); -}); -``` - -#### `server.stop([options], [callback])` - -Stops the server by refusing to accept any new connections. Existing connections will continue until closed or timeout (defaults to 5 seconds). -Once the server stopped, all the connections have ended, and it is safe to exit the process, the callback (if provided) is called. If the server -is already stopped, the `callback()` is called on the next tick. - -The optional `options` object supports: - -- `timeout` - overrides the timeout in millisecond before forcefully terminating a connection. Defaults to `5000` (5 seconds). - -```javascript -server.stop({ timeout: 60 * 1000 }, function () { - - console.log('Server stopped'); -}); -``` - -#### `server.route(options)` - -Adds a new route to the server where: - -- `options` - the route configuration as described in [route options](#route-options). - -##### Route options - -The following options are available when adding a route: - -- `path` - (required) the absolute path used to match incoming requests (must begin with '/'). Incoming requests are compared to the configured - paths based on the server [`router`](#server.config.router) configuration option. The path can include named parameters enclosed in `{}` which - will be matched against literal values in the request as described in [Path parameters](#path-parameters). -

-- `method` - (required) the HTTP method. Typically one of 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'. Any HTTP method is allowed, except for 'HEAD'. - Use `*` to match against any HTTP method (only when an exact match was not found). -

-- `vhost` - an optional domain string or an array of domain strings for limiting the route to only requests with a matching host header field. - Matching is done against the hostname part of the header only (excluding the port). Defaults to all hosts. -

-- `handler` - (required) the function called to generate the response after successful authentication and validation. The handler function is - described in [Route handler](#route-handler). Alternatively, `handler` can be set to the string `'notfound'` to return a Not Found (404) - error response, or `handler` can be assigned an object with one of: - - `file` - generates a static file endpoint for serving a single file. `file` can be set to: - - a relative or absolute file path string (relative paths are resolved based on the server [`files`](#server.config.files) configuration). - - a function with the signature `function(request)` which returns the relative or absolute file path. - - an object with the following options: - - `path` - a path string or function as described above. - - `mode` - specifies whether to include the 'Content-Disposition' header with the response. Available values: - - `false` - header is not included. This is the default value. - - `'attachment'` - - `'inline'` -

- - `directory` - generates a directory endpoint for serving static content from a directory. Routes using the directory handler must include a - single path parameter at the end of the path string (e.g. '/path/to/somewhere/{param}' where the parameter name does not matter). The path - parameter can use any of the parameter options (e.g. '{param}' for one level files only, '{param?}' for one level files or the directory root, - '{param*}' for any level, or '{param*3}' for a specific level). The directory handler is an object with the following options: - - `path` - (required) the directory root path (relative paths are resolved based on the server [`files`](#server.config.files) configuration). - Value can be: - - a single path string used as the prefix for any resources requested by appending the request path parameter to the provided string. - - an array of path strings. Each path will be attempted in order until a match is found (by following the same process as the single path string). - - a function with the signature `function(request)` which returns the path string. - - `index` - optional boolean, determines if 'index.html' will be served if found in the folder when requesting a directory. Defaults to `true`. - - `listing` - optional boolean, determines if directory listing is generated when a directory is requested without an index document. - Defaults to `false`. - - `showHidden` - optional boolean, determines if hidden files will be shown and served. Defaults to `false`. - - `redirectToSlash` - optional boolean, determines if requests for a directory without a trailing slash are redirected to the same path with - the missing slash. Useful for ensuring relative links inside the response are resolved correctly. -

- - `proxy` - generates a reverse proxy handler with the following options: - - `host` - the upstream service host to proxy requests to. The same path on the client request will be used as the path on the host. - - `port` - the upstream service port. - - `protocol` - The protocol to use when making a request to the proxied host: - - `'http'` - - `'https'` - - `passThrough` - if `true`, forwards the headers sent from the client to the upstream service being proxied to. Defaults to `false`. - - `rejectUnauthorized` - sets the _'rejectUnauthorized'_ property on the https [agent](http://nodejs.org/api/https.html#https_https_request_options_callback) making the request. - This value is only used when the proxied server uses TLS/SSL. When set it will override the node.js _'rejectUnauthorized'_ property. If _'false'_ then ssl errors will be ignored. - When _'true'_ the server certificate is verified and an 500 response will be sent when verification fails. Defaults to the https agent default value of _'true'_. - - `xforward` - if `true`, sets the 'X-Forwarded-For', 'X-Forwarded-Port', 'X-Forwarded-Proto' headers when making a request to the - proxied upstream endpoint. Defaults to `false`. - - `redirects` - the maximum number of HTTP redirections allowed, to be followed automatically by the handler. Set to `false` or `0` to - disable all redirections (the response will contain the redirection received from the upstream service). If redirections are enabled, - no redirections (301, 302, 307, 308) will be passed along to the client, and reaching the maximum allowed redirections will return an - error response. Defaults to `false`. - - `mapUri` - a function used to map the request URI to the proxied URI. Cannot be used together with `host`, `port`, or `protocol`. - The function signature is `function(request, callback)` where: - - `request` - is the incoming `request` object - - `callback` - is `function(err, uri, headers)` where: - - `err` - internal error condition. - - `uri` - the absolute proxy URI. - - `headers` - optional object where each key is an HTTP request header and the value is the header content. - - `postResponse` - a custom function for processing the response from the upstream service before sending to the client. Useful for - custom error handling of responses from the proxied endpoint or other payload manipulation. Function signature is - `function(request, settings, res, payload)` where: - - `request` - is the incoming `request` object. It is the responsibility of the `postResponse()` function to call `request.reply()`. - - `settings` - the proxy handler configuration. - - `res` - the node response object received from the upstream service. - - `payload` - the response payload. -

- - `view` - generates a template-based response. The `view` options is set to the desired template file name. - The view context available to the template includes: - - `payload` - maps to `request.payload`. - - `params` - maps to `request.params`. - - `query` - maps to `request.query`. -

-- `config` - additional route configuration (the `config` options allows splitting the route information from its implementation): - - `handler` - an alternative location for the route handler function. Same as the `handler` option in the parent level. Can only - include one handler per route. -

- - `pre` - an array with prerequisites methods which are executed in serial or in parallel before the handler is called and are - described in [Route prerequisites](#route-prerequisites). -

- - `validate` - - `query` - validation rules for an incoming request URI query component (the key-value part of the URI between '?' and '#'). - The query is parsed into its individual key-value pairs (see - [Query String](http://nodejs.org/api/querystring.html#querystring_querystring_parse_str_sep_eq_options)) and stored in - `request.query` prior to validation. Values allowed: - - `true` - any query parameters allowed (no validation performed). This is the default. - - `false` - no query parameters allowed. - - a validation rules object as described in the [Joi](http://github.com/spumko/joi) module. -

- - `payload` - validation rules for an incoming request payload (request body). Values allowed: - - `true` - any payload allowed (no validation performed). This is the default. - - `false` - no payload allowed. - - a validation rules object as described in the [Joi](http://github.com/spumko/joi) module. -

- - `path` - validation rules for incoming request path parameters, after matching the path against the route and extracting any - parameters then stored in `request.params`. Values allowed: - - `true` - any path parameters allowed (no validation performed). This is the default. - - `false` - no path variables allowed. - - a validation rules object as described in the [Joi](http://github.com/spumko/joi) module. -

- - `response` - validation rules for the outgoing response payload (response body). Can only validate [object](#obj) response. Values allowed: - - `true` - any payload allowed (no validation performed). This is the default. - - `false` - no payload allowed. - - an object with the following options: - - `schema` - the validation schema as described in the [Joi](http://github.com/spumko/joi) module. - - `sample` - the percent of responses validated (0 - 100). Set to `0` to disable all validation. Defaults to `100` (all responses). - - `failAction` - defines what to do when a response fails validation. Options are: - - `error` - return an Internal Server Error (500) error response. This is the default value. - - `log` - log the error but send the response. -

- - `payload` - determines how the request payload is processed. `payload` can be assigned a string with the parsing mode directly (e.g. `'parse'`) - which will use the default values of the other settings, or an object with the following: - - `mode` - the parsing mode. Defaults to `'parse'` if `validate.payload` is set or when `method` is - `'POST'`, `'PUT'` or `'PATCH'`, otherwise `'stream'`. Payload processing is configured using the server [`payload`](#server.config.payload) configuration. - Options are: - - `'stream'` - the incoming request stream is left untouched, leaving it up to the handler to process the request via `request.raw.req`. - - `'raw'` - the payload is read and stored in `request.rawPayload` as a `Buffer` and is not parsed. - - `'parse'` - the payload is read and stored in `request.rawPayload` as a `Buffer`, and then parsed (JSON or form-encoded) and stored - in `request.payload`. Parsing is performed based on the incoming request 'Content-Type' header. If the parsing is enabled and the - format is unknown, a Bad Request (400) error response is sent. The supported mime types are: - - application/json - - application/x-www-form-urlencoded - - application/octet-stream - - multipart/form-data ([multiparty](https://npmjs.org/package/multiparty) is used for processing this data and is capable of - receiving files as well as other form data. All values are assigned to their respective form names in `request.payload`. - - `'try'` - same as `'parse'` but does not return an error on failed parsing. Instead, leaves `request.payload` undefined. - - `allow` - a string or an array of strings with the allowed mime types for the endpoint. Defaults to any of the supported mime types listed - above. Note that allowing other mime types not listed will not enable them to be parsed, and that if parsing mode is `'parse'`, the request - will result in an error response. - - `override` - a mime type string overriding the 'Content-Type' header value received. Defaults to no override. -

- - `cache` - if the route method is 'GET', the route can be configured to use the cache. The `cache` options are described in - the [**catbox** module documentation](https://github.com/spumko/catbox#policy) with some additions: - - `mode` - cache location. Available values: - - `'client'` - caching is performed on the client by sending the HTTP `Cache-Control` header. This is the default value. - - `'server'` - caching is performed on the server using the cache strategy configured. - - `'client+server'` - caching it performed on both the client and server. - - `segment` - optional segment name, used to isolate cached items within the cache partition. Defaults to the route fingerprint - (the route path with parameters represented by a `'?'` character). Note that when using the MongoDB cache strategy, some paths - will require manual override as their fingerprint will conflict with MongoDB collection naming rules. When setting segment - names manually, the segment must begin with `'//'`. - - `privacy` - determines the privacy flag included in client-side caching using the 'Cache-Control' header. Values are: - - `'default'` - no privacy flag. This is the default setting. - - `'public'` - mark the response as suitable for public caching. - - `'private'` - mark the response as suitable only for private caching. - - `expiresIn` - relative expiration expressed in the number of milliseconds since the item was saved in the cache. Cannot be used - together with `expiresAt`. - - `expiresAt` - time of day expressed in 24h notation using the 'MM:HH' format, at which point all cache records for the route - expire. Cannot be used together with `expiresIn`. - - `staleIn` - number of milliseconds to mark an item stored in cache as stale and reload it. Must be less than `expiresIn`. Available - only when using server-side caching. - - `staleTimeout` - number of milliseconds to wait before checking if an item is stale. Available only when using server-side caching. -

- - `auth` - authentication configuration. Value can be: - - a string with the name of an authentication strategy registered with `server.auth()`. - - a boolean where `false` means no authentication, and `true` sets to the default authentication strategy which is available only - when a single strategy is configured. - - an object with: - - `mode` - the authentication mode. Defaults to `'required'` if a server authentication strategy is configured, otherwise defaults - to no authentication. Available values: - - `'required'` - authentication is required. - - `'optional'` - authentication is optional (must be valid if present). - - `'try'` - same as `'optional'` but allows for invalid authentication. - - `strategies` - a string array of strategy names in order they should be attempted. If only one strategy is used, `strategy` can - be used instead with the single string value. Defaults to the default authentication strategy which is available only when a single - strategy is configured. - - `payload` - if set, the payload (in requests other than 'GET' and 'HEAD') is authenticated after it is processed. Requires a strategy - with payload authentication support (e.g. [Hawk](#hawk-authentication)). Available values: - - `false` - no payload authentication. This is the default value. - - `'required'` - payload authentication required. - - `'optional'` - payload authentication performed only when the client includes payload authentication information (e.g. - `hash` attribute in Hawk). - - `tos` - minimum terms-of-service version required (uses the [semver](https://npmjs.org/package/semver) module). If defined, the - authentication credentials object must include a `tos` key which satisfies this requirement. Defaults to `false` which means no validation. - - `scope` - required application scope. A scope string which must be included in the authentication credentials object in `scope` which is - a string array. Defaults to no scope required. - - `entity` - the required authenticated entity type. If set, must match the `entity` value of the authentication credentials. Available - values: - - `any` - the authentication can be on behalf of a user or application. This is the default value. - - `user` - the authentication must be on behalf of a user. - - `app` - the authentication must be on behalf of an application. -

- - `jsonp` - enables JSONP support by setting the value to the query parameter name containing the function name used to wrap the response payload. - For example, if the value is `'callback'`, a request comes in with `'callback=me'`, and the JSON response is `'{ "a":"b" }'`, the payload will be: - `'me({ "a":"b" });'`. -

- - `description` - route description used for generating documentation (string). - - `notes` - route notes used for generating documentation (string or array of strings). - - `tags` - route tags used for generating documentation (array of strings). - -```javascript -var Hapi = require('hapi'); -var server = new Hapi.Server(); - -// Handler in top level - -var status = function () { - - this.reply('ok'); -}; - -server.route({ method: 'GET', path: '/status', handler: status }); - -// Handler in config - -var user = { - cache: { expiresIn: 5000 }, - handler: function () { - - this.reply({ name: 'John' }); - } -}; - -server.route({ method: 'GET', path: '/user', config: user }); -``` - -##### Path processing - -The router iterates through the routing table on each incoming request and executes the first (and only the first) matching route. Route -matching is done on the request path only (excluding the query and other URI components). Requests are matches in a deterministic order where -the order in which routes are added does not matter. The routes are sorted from the most specific to the most generic. For example, the following -path array shows the order in which an incoming request path will be matched against the routes: - -```javascript -var paths = [ - '/', - '/a', - '/b', - '/ab', - '/{p}', - '/a/b', - '/a/{p}', - '/b/', - '/a/b/c', - '/a/b/{p}', - '/a/{p}/b', - '/a/{p}/c', - '/a/{p*2}', - '/a/b/c/d', - '/a/b/{p*2}', - '/a/{p}/b/{x}', - '/{p*5}', - '/a/b/{p*}', - '/{p*}' -]; -``` - -##### Path parameters - -Parameterized paths are processed by matching the named parameters to the content of the incoming request path at that path segment. For example, -'/book/{id}/cover' will match '/book/123/cover' and `request.params.id` will be set to `'123'`. Each path segment (everything between the opening '/' and - the closing '/' unless it is the end of the path) can only include one named parameter. - - An optional '?' suffix following the parameter name indicates an optional parameter (only allowed if the parameter is at the ends of the path). - For example, the route '/book/{id?}' matches '/book/'. - -```javascript -var getAlbum = function () { - - this.reply('You asked for ' + - (this.params.song ? this.params.song + ' from ' : '') + - this.params.album); -}; - -server.route({ - path: '/{album}/{song?}', - method: 'GET', - handler: getAlbum -}); -``` - -In addition to the optional '?' suffix, a parameter name can also specify the number of matching segments using the '*' suffix, followed by a number -greater than 1. If the number of expected parts can be anything, then use '*' without a number (matching any number of segments can only be used in the -last path segment). - -```javascript -var getPerson = function () { - - var nameParts = this.params.name.split('/'); - this.reply({ first: nameParts[0], last: nameParts[1] }); -}; - -server.route({ - path: '/person/{name*2}', // Matches '/person/john/doe' - method: 'GET', - handler: getPerson -}); -``` - -##### Route handler - -When a route is matched against an incoming request, the route handler is called and passed a reference to the [request](#request-object) object. -The handler method must call [`request.reply()`](#requestreplyresult) or one of its sub-methods to return control back to the router. - -Route handler functions can use one of three declaration styles: - -No arguments (the `request` object is bound to `this`, decorated by the `reply` interface): - -```javascript -var handler = function () { - - this.reply('success'); -}; -``` - -One argument (the request is passed as an argument, decorated by the `reply` interface): - -```javascript -var handler = function (request) { - - request.reply('success'); -}; -``` - -Two arguments (the request and the `reply` interface are passed as arguments): - -```javascript -var handler = function (request, reply) { - - reply('success'); -}; -``` - -The two-arguments style is provided for symmetry with extension functions and prerequisite functions where the function -signature is `function(request, next)`. In order to enable interchangeable use of these functions, the two argument style does -not provide any of the [`request.reply`](#requestreplyresult) decorations. - -##### Route prerequisites - -It is often necessary to perform prerequisite actions before the handler is called (e.g. load required reference data from a database). -The route `pre` option allows defining such pre-handler methods. The methods are called in order, unless a `mode` is specified with value -`'parallel'` in which case, all the parallel methods are executed first, then the rest in order. `pre` can be assigned a mixed array of: - -- objects with: - - `method` - the function to call (or short-hand helper string as described below). The function signature is `function(request, next)` where: - - `request` - the incoming `request` object. - - `next` - the function called when the method is done with the signature `function(result)` where: - - `result` - any return value including an `Error` object (created via `new Error()` or [`Hapi.error`](#hapierror)). If an error - is returned, that value is sent back to the client and the handler method is not called. - - `assign` - key name to assign the result of the function to within `request.pre`. - - `mode` - set the calling order of the function. Available values: - - `'serial'` - serial methods are executed after all the `'parallel'` methods in the order listed. This is the default value. - - `'parallel'` - all parallel methods are executed first in parallel before any serial method. The first to return an error response - will exist the set. -- functions - same as including an object with a single `method` key. -- strings - special short-hand notation for [registered server helpers](#serverhelpername-method-options) using the format 'name(args)' - (e.g. `'user(params.id)'`) where: - - 'name' - the helper name. The name is also used as the default value of `assign`. - - 'args' - the helper arguments (excluding `next`) where each argument is a property of `request`. - -```javascript -var Hapi = require('hapi'); -var server = new Hapi.Server(); - -var pre1 = function (request, next) { - - next('Hello'); -}; - -var pre2 = function (request, next) { - - next('World'); -}; - -var pre3 = function (request, next) { - - next(request.pre.m1 + ' ' + request.pre.m2); -}; - -server.route({ - method: 'GET', - path: '/', - config: { - pre: [ - { method: pre1, assign: 'm1', mode: 'parallel' }, - { method: pre2, assign: 'm2', mode: 'parallel' }, - { method: pre3, assign: 'm3' }, - ], - handler: function () { - - this.reply(this.pre.m3 + '\n'); - } - } -}); -``` - -##### Route not found - -If the application needs to override the default Not Found (404) error response, it can add a catch-all route for a specific -method or all methods. Only one catch-all route can be defined per server instance. - -```javascript -var Hapi = require('hapi'); -var server = new Hapi.Server(); - -var handler = function () { - - this.reply('The page was not found').code(404); -}; - -server.route({ method: '*', path: '/{p*}', handler: handler }); -``` - -#### `server.route(routes)` - -Same as [server.route(options)](#serverrouteoptions) where `routes` is an array of route options. - -```javascript -server.route([ - { method: 'GET', path: '/status', handler: status }, - { method: 'GET', path: '/user', config: user } -]); -``` - -#### `server.routingTable()` - -Returns a copy of the routing table. The return value is an array of routes where each route contains: - -- `settings` - the route config with defaults applied. -- `method` - the HTTP method in lower case. -- `path` - the route path. - -```javascript -var table = server.routingTable() -console.log(table); - -/* Output: - - [{ - method: 'get', - path: '/test/{p}/end', - settings: { - handler: [Function], - method: 'get', - plugins: {}, - app: {}, - validate: {}, - payload: 'stream', - auth: undefined, - cache: [Object] } - }] */ -``` - -#### `server.log(tags, [data, [timestamp]])` - -The `server.log()` method is used for logging server events that cannot be associated with a specific request. When called the server emits a `'log'` -event which can be used by other listeners or plugins to record the information or output to the console. The arguments are: - -- `tags` - a string or an array of strings (e.g. `['error', 'database', 'read']`) used to identify the event. Tags are used instead of log levels - and provide a much more expressive mechanism for describing and filtering events. Any logs generated by the server internally include the `'hapi'` - tag along with event-specific information. -- `data` - an optional message string or object with the application data being logged. -- `timestamp` - an optional timestamp expressed in milliseconds. Defaults to `Date.now()` (now). - -```javascript -var Hapi = require('hapi'); -var server = new Hapi.Server(); - -server.on('log', function (event, tags) { - - if (tags.error) { - console.log(event); - } -}); - -server.log(['test', 'error'], 'Test event'); -``` - -#### `server.state(name, [options])` - -[HTTP state management](http://tools.ietf.org/html/rfc6265) uses client cookies to persist a state across multiple requests. Cookie definitions -can be registered with the server using the `server.state()` method, where: - -- `name` - is the cookie name. -- `options` - are the optional cookie settings: - - `ttl` - time-to-live in milliseconds. Defaults to `null` (session time-life - cookies are deleted when the browser is closed). - - `isSecure` - sets the 'Secure' flag. Defaults to `false`. - - `isHttpOnly` - sets the 'HttpOnly' flag. Defaults to `false`. - - `path` - the path scope. Defaults to `null` (no path). - - `domain` - the domain scope. Defaults to `null` (no domain). - - `autoValue` - if present and the cookie was not received from the client or explicitly set by the route handler, the cookie is automatically - added to the response with the provided value. - - `encoding` - encoding performs on the provided value before serialization. Options are: - - `'none'` - no encoding. When used, the cookie value must be a string. This is the default value. - - `'base64'` - string value is encoded using Base64. - - `'base64json'` - object value is JSON-stringified than encoded using Base64. - - `'form'` - object value is encoded using the _x-www-form-urlencoded_ method. - - `'iron'` - Encrypts and sign the value using [**iron**](https://github.com/hueniverse/iron). - - `sign` - an object used to calculate an HMAC for cookie integrity validation. This does not provide privacy, only a mean to verify that the cookie value - was generated by the server. Redundant when `'iron'` encoding is used. Options are: - - `integrity` - algorithm options. Defaults to [`require('iron').defaults.integrity`](https://github.com/hueniverse/iron#options). - - `password` - password used for HMAC key generation. - - `password` - password used for `'iron'` encoding. - - `iron` - options for `'iron'` encoding. Defaults to [`require('iron').defaults`](https://github.com/hueniverse/iron#options). - -```javascript -// Set cookie definition - -server.state('session', { - ttl: 24 * 60 * 60 * 1000, // One day - isSecure: true, - path: '/', - encoding: 'base64json' -}); - -// Set state in route handler - -var handler = function () { - - var session = this.state.session; - if (!session) { - session = { user: 'joe' }; - } - - session.last = Date.now(); - - this.reply('Success').state('session', session); -}; -``` - -Registered cookies are automatically parsed when received. Parsing rules depends on the server [`state.cookies`](#server.config.state) configuration. -If an incoming registered cookie fails parsing, it is not included in `request.state`, regardless of the `state.cookies.failAction` setting. -When `state.cookies.failAction` is set to `'log'` and an invalid cookie value is received, the server will emit a `'request'` event. To capture these errors -subscribe to the `'request'` events and filter on `'error'` and `'state'` tags: - -```javascript -server.on('request', function (request, event, tags) { - - if (tags.error && tags.state) { - console.error(event); - } -}); -``` - -#### `server.views(options)` - -Initializes the server views manager programmatically instead of via the server [`views`](#server.config.views) configuration option. -The `options` object is the same as the server [`views`](#server.config.views) config object. - -```javascript -server.views({ - engines: { - html: 'handlebars', - jade: 'jade' - }, - path: '/static/templates' -}); -``` - -#### `server.auth(name, options)` - -Registers an authentication strategy where: - -- `name` - is the strategy name (`'default'` is automatically assigned if a single strategy is registered via the server `auth` config). -- `options` - required strategy options. Each scheme comes with its own set of required options, in addition to the options sharedby all schemes: - - `scheme` - (required, except when `implementation` is used) the built-in scheme name. Available values: - - `'basic'` - [HTTP Basic authentication](#basic-authentication) ([RFC 2617](http://tools.ietf.org/html/rfc2617)) - - `'cookie'` - [cookie authentication](#cookie-authentication) - - `'hawk'` - [HTTP Hawk authentication](#hawk-authentication) ([Hawk protocol](https://github.com/hueniverse/hawk)) - - `'bewit'` - [URI Bewit (Hawk)](#bewit-authentication) query authentication ([Hawk protocol](https://github.com/hueniverse/hawk)) - - `implementation` - an object with the **hapi** authentication scheme interface (use the `'hawk'` implementation as template). Cannot be used together with `scheme`. - - `defaultMode` - if `true`, the scheme is automatically assigned as a required strategy to any route without an `auth` config. Can only be assigned to a single - server strategy. Value must be `true` (which is the same as `'required'`) or a valid authentication mode (`'required'`, `'optional'`, `'try'`). Defaults to `false`. - -##### Basic authentication - -Basic authentication requires validating a username and password combination. The `'basic'` scheme takes the following required options: - -- `scheme` - set to `'basic'`. -- `validateFunc` - a user lookup and password validation function with the signature `function(username, password, callback)` where: - - `username` - the username received from the client. - - `password` - the password received from the client. - - `callback` - a callback function with the signature `function(err, isValid, credentials)` where: - - `err` - an internal error. - - `isValid` - `true` if both the username was found and the password matched, otherwise `false`. - - `credentials` - a credentials object passed back to the application in `request.auth.credentials`. Typically, `credentials` are only - included when `isValid` is `true`, but there are cases when the application needs to know who tried to authenticate even when it fails - (e.g. with authentication mode `'try'`). - -```javascript -var Bcrypt = require('bcrypt'); - -var users = { - john: { - username: 'john', - password: '$2a$10$iqJSHD.BGr0E2IxQwYgJmeP3NvhPrXAeLSaGCj6IR/XU5QtjVu5Tm', // 'secret' - name: 'John Doe', - id: '2133d32a' - } -}; - -var validate = function (username, password, callback) { - - var user = users[username]; - if (!user) { - return callback(null, false); - } - - Bcrypt.compare(password, user.password, function (err, isValid) { - - callback(err, isValid, { id: user.id, name: user.name }); - }); -}; - -server.auth('simple', { - scheme: 'basic', - validateFunc: validate -}); - -server.route({ method: 'GET', path: '/', config: { auth: 'simple' } }); -``` - -##### Cookie authentication - -Cookie authentication provides a simple cookie-based session management. The user has to be authenticated via other means, typically a web -form, and upon successful authentication, receive a reply with a session cookie. Subsequent requests containing the session cookie are authenticated -(the cookie uses [Iron](https://github.com/hueniverse/iron) to encrypt and sign the session content) and validated via the provided `validateFunc` -in case the cookie's encrypted content requires validation on each request. Note that cookie operates as a bearer token and anyone in possession -of the cookie content can use it to impersonate its true owner. The `'cookie`' scheme takes the following required options: - -- `scheme` - set to `'cookie'`. -- `cookie` - the cookie name. Defaults to `'sid'`. -- `password` - used for Iron cookie encoding. -- `ttl` - sets the cookie expires time in milliseconds. Defaults to single browser session (ends when browser closes). -- `clearInvalid` - if `true`, any authentication cookie that fails validation will be marked as expired in the response and cleared. Defaults to `false`. -- `isSecure` - if `false`, the cookie is allowed to be transmitted over insecure connections which exposes it to attacks. Defaults to `true`. -- `isHttpOnly` - if `false`, the cookie will not include the 'HttpOnly' flag. Defaults to `true`. -- `redirectTo` - optional login URI to redirect unauthenticated requests to. Defaults to no redirection. -- `appendNext` - if `true` and `redirectTo` is `true`, appends the current request path to the query component of the `redirectTo` URI using the - parameter name `'next'`. Set to a string to use a different parameter name. Defaults to `false`. -- `validateFunc` - an optional session validation function used to validate the content of the session cookie on each request. Used to verify that the - internal session state is still valid (e.g. user account still exists). The function has the signature `function(session, callback)` where: - - `session` - is the session object set via `request.auth.session.set()`. - - `callback` - a callback function with the signature `function(err, isValid, credentials)` where: - - `err` - an internal error. - - `isValid` - `true` if the content of the session is valid, otherwise `false`. - - `credentials` - a credentials object passed back to the application in `request.auth.credentials`. If value is `null` or `undefined`, - defaults to `session`. If set, will override the current cookie as if `request.auth.session.set()` was called. - -When the cookie scheme is enabled on a route, the `request.auth.session` objects is decorated with two methods: - -- `set(session)` - sets the current session. Must be called after a successful login to begin the session. `session` must be a non-null object, - which is set on successful subsequent authentications in `request.auth.credentials`. -- `clear()` - clears the current session. Used to logout a user. - -Because this scheme decorates the `request` object with session-specific methods, it cannot be registered more than once. - -```javascript -var Hapi = require('hapi'); - -var users = { - john: { - id: 'john', - password: 'password', - name: 'John Doe' - } -}; - -var home = function () { - - this.reply('Login page

Welcome ' - + this.auth.credentials.name - + '!


' - + '' - + '
'); -}; - -var login = function () { - - if (this.auth.isAuthenticated) { - return this.reply.redirect('/'); - } - - var message = ''; - var account = null; - - if (this.method === 'post') { - - if (!this.payload.username || - !this.payload.password) { - - message = 'Missing username or password'; - } - else { - account = users[this.payload.username]; - if (!account || - account.password !== this.payload.password) { - - message = 'Invalid username or password'; - } - } - } - - if (this.method === 'get' || - message) { - - return this.reply('Login page' - + (message ? '

' + message + '


' : '') - + '
' - + 'Username:
' - + 'Password:
' - + '
'); - } - - this.auth.session.set(account); - return this.reply.redirect('/'); -}; - -var logout = function () { - - this.auth.session.clear(); - return this.reply.redirect('/'); -}; - -var server = new Hapi.Server('localhost', 8000); - -server.auth('session', { - scheme: 'cookie', - password: 'secret', - cookie: 'sid-example', - redirectTo: '/login' -}); - -server.route([ - { method: 'GET', path: '/', config: { handler: home, auth: true } }, - { method: '*', path: '/login', config: { handler: login, auth: { mode: 'try' } } }, - { method: 'GET', path: '/logout', config: { handler: logout, auth: true } } -]); - -server.start(); -``` - -##### Hawk authentication - -[Hawk authentication](https://github.com/hueniverse/hawk) provides a holder-of-key authentication scheme. The scheme supports payload -authentication. The scheme requires the following options: - -- `scheme` - set to `'hawk'`. -- `getCredentialsFunc` - credential lookup function with the signature `function(id, callback)` where: - - `id` - the Hawk credentials identifier. - - `callback` - the callback function with signature `function(err, credentials)` where: - - `err` - an internal error. - - `credentials` - a credentials object passed back to the application in `request.auth.credentials`. Return `null` or `undefined` to - indicate unknown credentials (which is not considered an error state). -- `hawk` - optional protocol options passed to `Hawk.server.authenticate()`. - -```javascript -var Hapi = require('hapi'); -var server = new Hapi.Server(config); - -var credentials = { - d74s3nz2873n: { - key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', - algorithm: 'sha256' - } -} - -var getCredentials = function (id, callback) { - - return callback(null, credentials[id]); -}; - -server.auth('hawk', { - scheme: 'hawk', - getCredentialsFunc: getCredentials -}); -``` - -##### Bewit authentication - -[Bewit authentication](https://github.com/hueniverse/hawk#single-uri-authorization) provides a short-term access to a protected resource by -including a token (bewit) in the request query, issued by an authorized party. Bewit is a subset of the Hawk protocol. The scheme can only -be used with 'GET' requests and requires the following options: - -- `scheme` - set to `'bewit'`. -- `getCredentialsFunc` - credential lookup function with the signature `function(id, callback)` where: - - `id` - the Hawk credentials identifier. - - `callback` - the callback function with signature `function(err, credentials)` where: - - `err` - an internal error. - - `credentials` - a credentials object passed back to the application in `request.auth.credentials`. Return `null` or `undefined` to - indicate unknown credentials (which is not considered an error state). -- `hawk` - optional protocol options passed to `Hawk.server.authenticateBewit()`. - -```javascript -var Hapi = require('hapi'); -var server = new Hapi.Server(config); - -var credentials = { - d74s3nz2873n: { - key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', - algorithm: 'sha256' - } -} - -var getCredentials = function (id, callback) { - - return callback(null, credentials[id]); -}; - -server.auth('bewit', { - scheme: 'bewit', - getCredentialsFunc: getCredentials -}); -``` - -To send an authenticated Bewit request, the URI must contain the `'bewit'` query parameter which can be generated using the Hawk module: - -```javascript -var Hawk = require('hawk'); - -var credentials = { - id: 'd74s3nz2873n', - key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', - algorithm: 'sha256' -}; - -var uri = 'http://example.com:8080/endpoint'; -var bewit = Hawk.client.getBewit(uri, { credentials: credentials, ttlSec: 60 }); -uri += '?bewit=' + bewit; -``` - -#### `server.ext(event, method, [options])` - -Registers an extension function in one of the available [extension points](#request-lifecycle) where: - -- `event` - the event name. -- `method` - a function or an array of functions to be executed at a specified point during request processing. The required extension function signature - is `function(request, next)` where: - - `request` - the incoming `request` object. - - `next` - the callback function the extension method must call to return control over to the router with signature `function(exit)` where: - - `exit` - optional request processing exit response. If set to a non-falsy value, the request lifecycle process will jump to the - "send response" step, skipping all other steps in between, and using the `exit` value as the new response. `exit` can be any result - value accepted by [`request.reply()`](#requestreplyresult). -- `options` - an optional object with the following: - - `before` - a string or array of strings of plugin names this method must executed before (on the same event). Otherwise, extension methods are executed - in the order added. - - `after` - a string or array of strings of plugin names this method must executed before (on the same event). Otherwise, extension methods are executed - in the order added. - -```javascript -var Hapi = require('hapi'); -var server = new Hapi.Server(); - -server.ext('onRequest', function (request, next) { - - // Change all requests to '/test' - request.setUrl('/test'); - next(); -}); - -var handler = function () { - - this.reply({ status: 'ok' }); -}; - -server.route({ method: 'GET', path: '/test', handler: handler }); -server.start(); - -// All requests will get routed to '/test' -``` - -##### Request lifecycle - -Each incoming request passes through a pre-defined set of steps, along with optional extensions: - -- **`'onRequest'`** extension point - - always called - - the `request` object passed to the extension functions is decorated with the `request.setUrl(url)` and `request.setMethod(verb)` methods. Calls to these methods - will impact how the request is routed and can be used for rewrite rules. -- Lookup route using request path -- Parse cookies -- **`'onPreAuth'`** extension point -- Authenticate request -- Read and parse payload -- Authenticate request payload -- **`'onPostAuth'`** extension point -- Validate path parameters -- Process query extensions (e.g. JSONP) -- Validate query -- Validate payload -- **`'onPreHandler'`** extension point -- Route prerequisites -- Route handler -- **`'onPostHandler'`** extension point - - the `request` object passed to the extension function is decorated with the `request.response()` method which returns the response object. The response object may be - modified. To return a different response (for example, replace an error with an HTML response), return the new response via `next(response)`. -- Validate response payload -- **`'onPreResponse'`** extension point - - always called - - the `request` object passed to the extension function is decorated with the `request.response()` method which returns the response object. The response object may be - modified. To return a different response (for example, replace an error with an HTML response), return the new response via `next(response)`. -- Send response (may emit `'internalError'` event) -- Emits `'response'` event -- Wait for tails -- Emits `'tail'` event - -#### `server.helper(name, method, [options])` - -Registers a server helper function. Server helpers are functions registered with the server and used throughout the application as -a common utility. Their advantage is in the ability to configure them to use the built-in cache and shared across multiple request -handlers without having to create a common module. - -Helpers are registered via `server.helper(name, method, [options])` where: - -- `name` - a unique helper name used to invoke the method via `server.helpers[name]`. -- `method` - the helper function with the signature is `function(arg1, arg2, ..., argn, next)` where: - - `arg1`, `arg2`, etc. - the helper function arguments. - - `next` - the function called when the helper is done with the signature `function(result)` where: - - `result` - any return value including an `Error` object (created via `new Error()` or [`Hapi.error`](#hapierror)). -- `options` - optional configuration: - - `cache` - cache configuration as described in [**catbox** module documentation](https://github.com/spumko/catbox#policy): - - `expiresIn` - relative expiration expressed in the number of milliseconds since the item was saved in the cache. Cannot be used - together with `expiresAt`. - - `expiresAt` - time of day expressed in 24h notation using the 'MM:HH' format, at which point all cache records for the route - expire. Cannot be used together with `expiresIn`. - - `staleIn` - number of milliseconds to mark an item stored in cache as stale and reload it. Must be less than `expiresIn`. - - `staleTimeout` - number of milliseconds to wait before checking if an item is stale. - - `segment` - optional segment name, used to isolate cached items within the cache partition. Defaults to '#name' where 'name' is the - helper name. When setting segment manually, it must begin with '##'. - - `generateKey` - a function used to generate a unique key (for caching) from the arguments passed to the helper function - (with the exception of the last 'next' argument). The server will automatically generate a unique key if the function's - arguments are all of types `'string'`, `'number'`, or `'boolean'`. However if the helper uses other types of arguments, a - key generation function must be provided which takes the same arguments as the function and returns a unique string (or - `null` if no key can be generated). Note that when the `generateKey` method is invoked, the arguments list will include - the `next` argument which must not be used in calculation of the key. - -```javascript -var Hapi = require('hapi'); -var server = new Hapi.Server(); - -// Simple arguments - -var add = function (a, b, next) { - - next(a + b); -}; - -server.helper('sum', add, { cache: { expiresIn: 2000 } }); - -server.helpers.sum(4, 5, function (result) { - - console.log(result); -}); - -// Object argument - -var addArray = function (array, next) { - - var sum = 0; - array.forEach(function (item) { - - sum += item; - }); - - next(sum); -}; - -server.helper('sumObj', addArray, { - cache: { expiresIn: 2000 }, - generateKey: function (array) { - - return array.join(','); - } -}); - -server.helpers.sumObj([5, 6], function (result) { - - console.log(result); -}); -``` - -#### `server.inject(options, callback)` - -Injects a request into the server simulating an incoming HTTP request without making an actual socket connection. Injection is useful for -testing purposes as well as for invoking routing logic internally without the overhead or limitations of the network stack. Utilizes the -[**shot**](https://github.com/spumko/shot) module for performing injections, with some additional options and response properties: - -- `options` - can be assign a string with the requested URI, or an object with: - - `method` - the request HTTP method (e.g. `'POST'`). Defaults to `'GET'`. - - `url` - the request URL. If the URI includes an authority (e.g. `'example.com:8080'`), it is used to automatically set an HTTP 'Host' - header, unless one was specified in `headers`. - - `headers` - an object with optional request headers where each key is the header name and the value is the header content. Defaults - to no additions to the default Shot headers. - - `payload` - an optional string or buffer containing the request payload (object must be manually converted to a string first). - Defaults to no payload. Note that payload processing defaults to `'application/json'` if no 'Content-Type' header provided. - - `credentials` - an optional credentials object containing authentication information. The `credentials` are used to bypass the default - authentication strategies, and are validated directly as if they were received via an authentication scheme. Defaults to no credentials. - - `simulate` - an object with options used to simulate client request stream conditions for testing: - - `error` - if `true`, emits an `'error'` event after payload transmission (if any). Defaults to `false`. - - `close` - if `true`, emits a `'close'` event after payload transmission (if any). Defaults to `false`. - - `end` - if `false`, does not end the stream. Defaults to `true`. -- `callback` - the callback function with signature `function(res)` where: - - `res` - the response object where: - - `statusCode` - the HTTP status code. - - `headers` - an array containing the headers set. - - `payload` - the response payload string. - - `rawPayload` - the raw response payload buffer. - - `raw` - an object with the injection request and response objects: - - `req` - the `request` object. - - `res` - the response object. - - `result` - the raw handler response (e.g. when not a stream) before it is serialized for transmission. If not available, set to - `payload`. Useful for inspection and reuse of the internal objects returned (instead of parsing the response string). - -```javascript -var Hapi = require('hapi'); -var server = new Hapi.Server(); - -var get = function () { - - this.reply('Success!'); -}; - -server.route({ method: 'GET', path: '/', handler: get }); - -server.inject('/', function (res) { - - console.log(res.result); -}); -``` - -### `Server` events - -The server object inherits from `Events.EventEmitter` and emits the following events: - -- `'log'` - events logged with [server.log()](#serverlogtags-data-timestamp). -- `'request'` - events generated by [request.log()](#requestlogtags-data-timestamp) or internally (multiple events per request). -- `'response'` - emitted after a response to a client request is sent back. Single event per request. -- `'tail'` - emitted when a request finished processing, including any registered [tails](#requesttailname). Single event per request. -- `'internalError'` - emitted whenever an Internal Server Error (500) error response is sent. Single event per request. - -When provided (as listed below) the `event` object include: - -- `timestamp` - the event timestamp. -- `id` - if the event relates to a request, the request id. -- `tags` - an array of tags (e.g. `['error', 'http']`). Includes the `'hapi'` tag is the event was generated internally. -- `data` - optional event-specific information. - -The `'log'` event includes the `event` object and a `tags` object (where each tag is a key with the value `true`): - -```javascript -server.on('log', function (event, tags) { - - if (tags.error) { - console.log('Server error: ' + (event.data || 'unspecified')); - } -}); -``` - -The `'request'` event includes the `request` object, the `event` object, and a `tags` object (where each tag is a key with the value `true`): - -```javascript -server.on('request', function (request, event, tags) { - - if (tags.received) { - console.log('New request: ' + event.id); - } -}); -``` - -The `'response'` and `'tail'` events include the `request` object: - -```javascript -server.on('response', function (request) { - - console.log('Response sent for request: ' + request.id); -}); -``` - -The `'internalError'` event includes the `request` object and the causing error `err` object: - -```javascript -server.on('internalError', function (request, err) { - - console.log('Error response (500) sent for request: ' + request.id + ' because: ' + err.message); -}); -``` - -## Request object - -The `request` object is created internally for each incoming request. It is **not** the node `request` object received from the HTTP -server callback (which is available in `request.raw.req`). The `request` object methods and properties change through the -[request lifecycle](#request-lifecycle). - -### `request` properties - -Each request object have the following properties: - -- `app` - application-specific state. Provides a safe place to store application data without potential conflicts with **hapi**. - Should not be used by plugins which should use `plugins[name]`. -- `auth` - authentication information: - - `isAuthenticated` - `true` is the request has been successfully authenticated, otherwise `false`. - - `credentials` - the `credential` object received during the authentication process. The presence of an object does not mean - successful authentication. - - `artifacts` - an artifact object received from the authentication strategy and used in authentication-related actions. - - `session` - an object used by the [`'cookie'` authentication scheme](#cookie-authentication). -- `id` - a unique request identifier. -- `info` - request information: - - `received` - request reception timestamp. - - `remoteAddress` - remote client IP address. - - `remotePort` - remote client port. - - `referrer` - content of the HTTP 'Referrer' (or 'Referer') header. - - `host` - content of the HTTP 'Host' header. -- `method` - the request method in lower case (e.g. `'get'`, `'post'`). -- `params` - an object where each key is a path parameter name with matching value as described in [Path parameters](#path-parameters). -- `path` - the request URI's path component. -- `payload` - an object containing the parsed request payload (when the route `payload` option is set to `'parse'`). -- `plugins` - plugin-specific state. Provides a place to store and pass request-level plugin data. The `plugins` is an object where each - key is a plugin name and the value is the state. -- `pre` - an object where each key is the name assigned by a [route prerequisites](#route-prerequisites) function. -- `query` - an object containing the query parameters. -- `raw` - an object containing the Node HTTP server objects. **Direct interaction with these raw objects is not recommended.** - - `req` - the `request` object. - - `res` - the response object. -- `rawPayload` - the raw request payload `Buffer` (except when the route `payload` option is set to `'stream'`). -- `route` - the route configuration object after defaults are applied. -- `server` - the server object. -- `session` - Special key reserved for plugins implementing session support. Plugins utilizing this key must check for `null` value - to ensure there is no conflict with another similar plugin. -- `state` - an object containing parsed HTTP state information (cookies) where each key is the cookie name and value is the matching - cookie content after processing using any registered cookie definition. -- `url` - the parsed request URI. - -### `request` methods - -#### `request.setUrl(url)` - -_Available only in `'onRequest'` extension methods._ - - Changes the request URI before the router begins processing the request where: - - - `url` - the new request path value. - -```javascript -var Hapi = require('hapi'); -var server = new Hapi.Server(); - -server.ext('onRequest', function (request, next) { - - // Change all requests to '/test' - request.setUrl('/test'); - next(); -}); -``` - -#### `request.setMethod(method)` - -_Available only in `'onRequest'` extension methods._ - -Changes the request method before the router begins processing the request where: - -- `method` - is the request HTTP method (e.g. `'GET'`). - -```javascript -var Hapi = require('hapi'); -var server = new Hapi.Server(); - -server.ext('onRequest', function (request, next) { - - // Change all requests to 'GET' - request.setMethod('GET'); - next(); -}); -``` - -#### `request.log(tags, [data, [timestamp]])` - -_Always available._ - -Logs request-specific events. When called, the server emits a `'request'` event which can be used by other listeners or plugins. The -arguments are: - -- `tags` - a string or an array of strings (e.g. `['error', 'database', 'read']`) used to identify the event. Tags are used instead of log levels - and provide a much more expressive mechanism for describing and filtering events. Any logs generated by the server internally include the `'hapi'` - tag along with event-specific information. -- `data` - an optional message string or object with the application data being logged. -- `timestamp` - an optional timestamp expressed in milliseconds. Defaults to `Date.now()` (now). - -```javascript -var Hapi = require('hapi'); -var server = new Hapi.Server(); - -server.on('request', function (request, event, tags) { - - if (tags.error) { - console.log(event); - } -}); - -var handler = function () { - - this.log(['test', 'error'], 'Test event'); -}; -``` - -#### `request.getLog([tags])` - -_Always available._ - -Returns an array containing the events matching any of the tags specified (logical OR) where: -- `tags` - is a single tag string or array of tag strings. If no `tags` specified, returns all events. - -```javascript -request.getLog(); -request.getLog('error'); -request.getLog(['hapi', 'error']); -``` - -#### `request.tail([name])` - -_Available until immediately after the `'response'` event is emitted._ - -Adds a request tail which has to complete before the request lifecycle is complete where: - -- `name` - an optional tail name used for logging purposes. - -Returns a tail function which must be called when the tail activity is completed. - -Tails are actions performed throughout the request lifecycle, but which may end after a response is sent back to the client. For example, a -request may trigger a database update which should not delay sending back a response. However, it is still desirable to associate the activity -with the request when logging it (or an error associated with it). - -When all tails completed, the server emits a `'tail'` event. - -```javascript -var Hapi = require('hapi'); -var server = new Hapi.Server(); - -var get = function (request) { - - var dbTail = request.tail('write to database'); - - db.save('key', 'value', function () { - - dbTail(); - }); - - request.reply('Success!'); -}; - -server.route({ method: 'GET', path: '/', handler: get }); - -server.on('tail', function (request) { - - console.log('Request completed including db activity'); -}); -``` - -#### `request.setState(name, value, [options])` - -_Available until immediately after the `'onPreResponse'` extension point methods are called._ - -Sets a cookie which is sent with the response, where: - -- `name` - the cookie name. -- `value` - the cookie value. If no `encoding` is defined, must be a string. -- `options` - optional configuration. If the state was previously registered with the server using [`server.state()`](#serverstatename-options), - the specified keys in `options` override those same keys in the server definition (but not others). - -```javascript -request.setState('preferences', { color: 'blue' }, { encoding: 'base64json' }); -``` - -#### `request.clearState(name)` - -_Available until immediately after the `'onPreResponse'` extension point methods are called._ - -Clears a cookie which sets an expired cookie and sent with the response, where: - -- `name` - the cookie name. - -```javascript -request.clearState('preferences'); -``` - -#### `request.reply([result])` - -_Available only within the handler method and only before one of `request.reply()`, `request.reply.redirection()`, `request.reply.view()`, or -`request.reply.close()` is called._ - -Concludes the handler activity by returning control over to the router where: - -- `result` - an optional response payload. - -Returns a [`response`](#response-types) object based on the value of `result`: - -- `null`, `undefined`, or empty string `''` - [`Empty`](#empty) response. -- string - [`Text`](#text) response. -- `Buffer` object - [`Buffer`](#buffer) response. -- `Error` object (generated via [`error`](#hapierror) or `new Error()`) - [`Boom`](#hapierror) object. -- `Stream` object - [`Stream`](#stream) response. -- any other object - [`Obj`](#obj) response. - -```javascript -var handler = function () { - - this.reply('success'); -}; -``` - -The returned `response` object provides a set of methods to customize the response (e.g. HTTP status code, custom headers, etc.). The methods -are response-type-specific and listed in [`response`](#response-types). - -```javascript -var handler = function () { - - this.reply('success') - .type('text/plain) - .header('X-Custom', 'some-value'); -}; -``` - -The [response flow control rules](#flow-control) apply. - -##### `request.reply.redirect(uri)` - -_Available only within the handler method and only before one of `request.reply()`, `request.reply.redirection()`, `request.reply.view()`, or -`request.reply.close()` is called._ - -Concludes the handler activity by returning control over to the router with a redirection response where: - -- `uri` - an absolute or relative URI used to redirect the client to another resource. If a relative URI is provided, the value of - the server [`location`](#server.config.location) configuration option is used as prefix. - -Returns a [`Redirection`](#redirection) response. - -```javascript -var handler = function () { - - this.reply.redirection('http://example.com/elsewhere') - .message('You are being redirected...') - .permanent(); -}; -``` - -The [response flow control rules](#flow-control) apply. - -##### `request.reply.view(template, [context, [options]])` - -_Available only within the handler method and only before one of `request.reply()`, `request.reply.redirection()`, `request.reply.view()`, or -`request.reply.close()` is called._ - -Concludes the handler activity by returning control over to the router with a templatized view response where: - -- `template` - the template filename and path, relative to the templates path configured via the server [`views.path`](#server.config.views). -- `context` - optional object used by the template to render context-specific result. Defaults to no context `{}`. -- `options` - optional object used to override the server's [`views`](#server.config.views) configuration for this response. - -Returns a [`View`](#view) response. - -```javascript -var Hapi = require('hapi'); -var server = new Hapi.Server({ - views: { - engines: { html: 'handlebars' }, - path: __dirname + '/templates' - } -}); - -var handler = function () { - - var context = { - title: 'Views Example', - message: 'Hello, World' - }; - - this.reply.view('hello', context); -}; - -server.route({ method: 'GET', path: '/', handler: handler }); -``` - -**templates/hello.html** - -```html - - - - {{title}} - - -
-

{{message}}

-
- - -``` - -The [response flow control rules](#flow-control) apply. - -##### `request.reply.close()` - -_Available only within the handler method and only before one of `request.reply()`, `request.reply.redirection()`, `request.reply.view()`, or -`request.reply.close()` is called._ - -Concludes the handler activity by returning control over to the router and informing the router that a response has already been sent back -directly via `request.raw.res` and that no further response action is needed (the router will ensure the `request.raw.res` was ended). - -No return value. - -The [response flow control rules](#flow-control) **do not** apply. - -#### `request.generateView(template, context, [options])` - -_Always available._ - -Returns a [`View`](#view) response object using the request environment where: - -- `template` - the template filename and path, relative to the templates path configured via the server [`views.path`](#server.config.views). -- `context` - optional object used by the template to render context-specific result. Defaults to no context `{}`. -- `options` - optional object used to override the server's [`views`](#server.config.views) configuration for this response. - -Useful when a view response is required outside of the handler (e.g. used in an extension point method to return an override response). - -```javascript -var Hapi = require('hapi'); -var server = new Hapi.Server({ views: { engines: { html: 'handlebars' } } }); - -server.ext('onPreResponse', function (request, next) { - - var response = request.response(); - if (!response.isBoom) { - return next(); - } - - // Replace error with friendly HTML - - var error = response; - var context = { - message: (error.response.code === 404 ? 'page not found' : 'something went wrong') - }; - - next(request.generateView('error', context)); -}); -``` - -#### `request.response()` - -_Available after the handler method concludes and immediately after the `'onPreResponse'` extension point methods._ - -Returns the response object. The object can be modified but cannot be assigned another object. To replace the response with another -from within an extension point, use `next(response)` to return a different response. - -```javascript -var Hapi = require('hapi'); -var server = new Hapi.Server(); - -server.ext('onPostHandler', function (request, next) { - - var response = request.response(); - if (response.variety === 'obj') { - delete response.raw._id; // Remove internal key - response.update(); - } - next(); -}); -``` - -## `Hapi.response` - -### Flow control - -When calling `request.reply()`, the router waits until `process.nextTick()` to continue processing the request and transmit the response. -This enables making changes to the returned response object before the response is sent. This means the router will resume as soon as the handler -method exists. To suspend this behavior, the returned `response` object includes: - -- `response.hold()` - puts the response on hold until `response.send()` is called. Available only after `request.reply()` is called and until - `response.hold()` is invoked once. -- `response.send()` - resume the response which will be transmitted in the next tick. Available only after `response.hold()` is called and until - `response.send()` is invoked once. - -```javascript -var handler = function () { - - var response = this.reply('success').hold(); - - onTimeout(function () { - - response.send(); - }, 1000); -}; -``` - -### Response types - -Every response type must include the following properties: - -- `variety` - the response type name in lower case (e.g. `'text'`). -- `varieties` - an object where each key has a `true` value and represents a response type name (in lower case) whose functionality is made - available via the response object (e.g. the `File` response type `varieties` object is `{ generic: true, stream: true, file: true }`). - -#### `Generic` - -The `Generic` response type is used as the parent prototype for all other response types. It cannot be instantiated directly and is only made available -for deriving other response types. It provides the following methods: - -- `code(statusCode)` - sets the HTTP status code where: - - `statusCode` - the HTTP status code. -- `header(name, value)` - sets an HTTP header where: - - `name` - the header name. - - `value` - the header value. -- `type(mimeType)` - sets the HTTP 'Content-Type' header where: - - `value` - is the mime type. Should only be used to override the built-in default for each response type. -- `created(location)` - sets the HTTP status code to Created (201) and the HTTP 'Location' header where: - `location` - an absolute or relative URI used as the 'Location' header value. If a relative URI is provided, the value of - the server [`location`](#server.config.location) configuration option is used as prefix. Not available in the `Redirection` - response object. -- `encoding(encoding)` - sets the 'Content-Type' HTTP header encoding property where: - `encoding` - the encoding property value. -- `ttl(msec)` - overrides the default route cache expiration rule for this response instance where: - - `msec` - the time-to-live value in milliseconds. -- `getTtl()` - returns the time-to-live value if an override has been set, and the request method is 'GET'. -- `state(name, value, [options])` - sets an HTTP cookie as described in [`request.setState()`](#requestsetstatename-value-options). -- `unstate(name)` - clears the HTTP cookie by setting an expired value as described in [`request.clearState()`](#requestclearstatename). - -#### `Empty` - -An empty response body (content-length of zero bytes). Supports all the methods provided by [`Generic`](#generic). - -Generated with: - -- `request.reply()` - without any arguments. -- `new Hapi.response.Empty()` - -```javascript -var handler1 = function () { - - this.reply(); -}; - -var handler2 = function () { - - var response = new Hapi.response.Empty(); - this.reply(response); -}; -``` - -#### `Text` - -Plain text. The 'Content-Type' header defaults to `'text/html'`. Supports all the methods provided by [`Generic`](#generic) as well as: - -- `message(text, [type, [encoding]])` - sets or replace the response text where: - - `text` - the text content. - - `type` - the 'Content-Type' HTTP header value. Defaults to `'text/html'`. - - `encoding` - the 'Content-Type' HTTP header encoding property. Defaults to `'utf-8'`. - -Generated with: - -- `request.reply(result)` - where: - - `result` - must be a non-empty string. -- `new Hapi.response.Text(text, [type, [encoding]])` - same as `message()` above. - -```javascript -var handler1 = function () { - - this.reply('hello world'); -}; - -var handler2 = function () { - - var response = new Hapi.response.Text('hello world'); - this.reply(response); -}; - -var handler3 = function () { - - var response = new Hapi.response.Text(); - response.message('hello world'); - this.reply(response); -}; -``` - -#### `Buffer` - -Buffer response. Supports all the methods provided by [`Generic`](#generic). - -Generated with: - -- `request.reply(result)` - where: - - `result` - must be a `Buffer`. -- `new Hapi.response.Buffer(buffer)` - where: - - `buffer` - the `Buffer` response. - -```javascript -var handler1 = function () { - - var buffer = new Buffer([10, 11, 12, 13]); - this.reply(buffer); -}; - -var handler2 = function () { - - var buffer = new Buffer([10, 11, 12, 13]); - var response = new Hapi.response.Buffer(buffer); - this.reply(response); -}; -``` - -#### `Stream` - -Replies with a stream object, directly piped into the HTTP response. Supports all the methods provided by [`Generic`](#generic) as well as: - -- `bytes(length)` - sets the HTTP 'Content-Length' header (to avoid chunked transfer encoding) where: - - `length` - the header value. Must match the actual payload size. - -Generated with: - -- `request.reply(result)` - where: - - `result` - must be a [`Stream.Readable`](http://nodejs.org/api/stream.html#stream_class_stream_readable) or a node 0.8.x `Stream`. -- `new Hapi.response.Stream(stream)` - where: - - `stream` - the [`Stream.Readable`](http://nodejs.org/api/stream.html#stream_class_stream_readable) or a node 0.8.x `Stream`. - -```javascript -var Stream = require('stream'); -var Hapi = require('hapi'); - -var ExampleStream = function () { - - Stream.Readable.call(this); -}; - -Hapi.utils.inherits(ExampleStream, Stream.Readable); - -ExampleStream.prototype._read = function (size) { - - this.push('hello world'); - this.push(null); -}; - -var handler1 = function () { - - var stream = new ExampleStream(); - this.reply(stream); -}; - -var handler2 = function () { - - var response = new Hapi.response.Stream(new ExampleStream()); - this.reply(response); -}; - -var handler3 = function () { - - // Echo back request stream - this.reply(this.raw.req).bytes(this.raw.req.headers['content-length']); -}; -``` - -#### `Obj` - -JavaScript object, sent stringified. The 'Content-Type' header defaults to 'application/json'. Supports all the methods provided by -[`Generic`](#generic) as well as: - -- `raw` - the unmodified, unstringified object. Any direct manipulation must be followed with `update()`. -- `update(type, encoding)` - updates the string representation of the object response after changes to `raw` where: - - `type` - the 'Content-Type' HTTP header value. Defaults to `'text/html'`. - - `encoding` - the 'Content-Type' HTTP header encoding property. Defaults to `'utf-8'`. - -```javascript -var Hapi = require('hapi'); -var server = new Hapi.Server(); - -server.ext('onPostHandler', function (request, next) { - - var response = request.response(); - if (response.variety === 'obj') { - delete response.raw._id; // Remove internal key - response.update(); - } - next(); -}); -``` - -Generated with: - -- `request.reply(result)` - where: - - `result` - must be an object. -- `new Hapi.response.Obj(object, [type, [encoding]])` - where: - - `object` - the response object. - - `type` - the 'Content-Type' HTTP header value. Defaults to `'text/html'`. - - `encoding` - the 'Content-Type' HTTP header encoding property. Defaults to `'utf-8'`. - -```javascript -var handler1 = function () { - - this.reply({ message: 'hello world' }); -}; - -var handler2 = function () { - - var response = new Hapi.response.Obj({ message: 'hello world' }); - this.reply(response); -}; -``` - -#### `File` - -Transmits a file from the file system. The 'Content-Type' header defaults to the matching mime type based on filename extension. Supports all the methods -provided by [`Stream`](#stream). - -Generated with: - -- `new Hapi.response.File(filePath, [options])` - where: - - `filePath` - a relative or absolute file path string (relative paths are resolved based on the server [`files`](#server.config.files) configuration). - - `options` - optional configuration: - - `mode` - value of the HTTP 'Content-Disposition' header. Allowed values: - - `'attachment'` - - `'inline'` -- the built-in route [`file`](#route.config.file) handler. - -```javascript -var Hapi = require('hapi'); -var server = new Hapi.Server({ files: { relativeTo: 'routes' } }); - -var handler1 = function () { - - var response = new Hapi.response.File('./hello.txt'); - this.reply(response); -}; - -server.route({ method: 'GET', path: '/1', handler: handler1 }); - -server.route({ method: 'GET', path: '/2', handler: { file: './hello.txt' } }); -``` - -#### `Directory` - -Transmits a file or list of files from the file system. The 'Content-Type' header defaults to the matching mime type based on filename -extension. This is an internal response time that can only be accessed via the built-in route handler. - -Generated with: - -- the built-in route [`directory`](#route.config.directory) handler. - -```javascript -var Hapi = require('hapi'); -var server = new Hapi.Server({ files: { relativeTo: 'cwd' } }); - -var handler1 = { - directory: { - path: ['./public1/', './public2/'], - listing: true - } -}; - -var handler2 = { - directory: { - path: function (request) { - - return (isMobileDevice(request) ? './mobile' : './public'); - } - } -}; - -server.route({ method: 'GET', path: '/1/{path*}', handler: handler1 }); -server.route({ method: 'GET', path: '/2/{path*}', handler: handler2 }); -``` - -#### `Redirection` - -An HTTP redirection response (3xx). Supports all the methods provided by [`Text`](#text) (except for `created()`) as well as the additional methods: - -- `uri(dest)` - set the destination URI where: - - `uri` - overrides the destination. An absolute or relative URI used as the 'Location' header value. If a relative URI is provided, the - value of the server [`location`](#server.config.location) configuration option is used as prefix. -- `temporary(isTemporary)` - sets the status code to `302` or `307` (based on the `rewritable()` setting) where: - - `isTemporary` - if `false`, sets status to permanent. Defaults to `true`. -- `permanent(isPermanent)` - sets the status code to `301` or `308` (based on the `rewritable()` setting) where: - - `isPermanent` - if `true`, sets status to temporary. Defaults to `false`. -- `rewritable(isRewritable)` - sets the status code to `301`/`302` for rewritable (allows changing the request method from 'POST' to 'GET') or - `307`/`308` for non-rewritable (does not allow changing the request method from 'POST' to 'GET'). Exact code based on the `temporary()` or - `permanent()` setting. Arguments: - - `isRewritable` - if `false`, sets to non-rewritable. Defaults to `true`. - -| | Permanent | Temporary | -| -------------- | ---------- | --------- | -| Rewritable | 301 | **302**(1)| -| Non-rewritable | 308(2) | 307 | - -Notes: -1. Default value. -2. [Proposed code](http://tools.ietf.org/id/draft-reschke-http-status-308-07.txt), not supported by all clients. - -Generated with: - -- `request.reply.redirect(uri)` - as described in [`request.reply.redirect()`](#requestreplyredirecturi). -- `new Hapi.response.Redirection(uri, [message, [type, [encoding]]])` - where: - - `uri` - an absolute or relative URI used as the 'Location' header value. If a relative URI is provided, the value of - the server [`location`](#server.config.location) configuration option is used as prefix. - - `message` - the payload content. Defaults to `'You are being redirected...'`. - - `type` - the 'Content-Type' HTTP header value. Defaults to `'text/html'`. - - `encoding` - the 'Content-Type' HTTP header encoding property. Defaults to `'utf-8'`. - -```javascript -var handler1 = function () { - - this.reply.redirect('http://example.com/elsewhere') - .temporary().rewritable(false); // 307 -}; - -var handler2 = function () { - - var response = new Hapi.response.Redirection('http://example.com/elsewhere'); - response.permanent().rewritable(); // 301 - this.reply(response); -}; -``` - -#### `View` - -Template-based response. Supports all the methods provided by [`Generic`](#generic). - -Generated with: - -- `request.reply.view(template, [context, [options]])` - as described in [`request.reply.view()`](#requestreplyviewtemplate-context-options). -- `request.generateView(template, context, [options])` - as described in [`request.generateView()`](#requestgenerateviewtemplate-context-options). -- the built-in route [`view`](#route.config.view) handler. - -```javascript -var Hapi = require('hapi'); -var server = new Hapi.Server({ - views: { - engines: { html: 'handlebars' }, - path: __dirname + '/templates' - } -}); - -var handler1 = function () { - - var context = { - params: { - user: this.params.user - } - }; - - this.reply.view('hello', context); -}; - -var handler2 = function () { - - var context = { - params: { - user: this.params.user - } - }; - - this.reply(this.generateView('hello', context)); -}; - -server.route({ method: 'GET', path: '/1/{user}', handler: handler1 }); -server.route({ method: 'GET', path: '/2/{user}', handler: handler2 }); -server.route({ method: 'GET', path: '/3/{user}', handler: { view: 'hello' } }); -``` - -**templates/hello.html** - -```html - - - - Hello World - - -
-

About {{ params.user }}

-
- - -``` - -#### `Cacheable` - -The `Cacheable` response type is used as the parent prototype for all cacheable response types. It cannot be instantiated directly and -is only made available for deriving other response types. - -## `Hapi.error` - -Provides a set of utilities for returning HTTP errors. An alias of the [**boom**](https://github.com/spumko/boom) module (can be also accessed -`Hapi.boom`). Each utility returns a `Boom` error response object (instance of `Error`) which includes the following properties: - -- `isBoom` - if `true`, indicates this is a `Boom` object instance. -- `message` - the error message. -- `response` - the formatted response. Can be directly manipulated after object construction to return a custom error response. Allowed root keys: - - `code` - the HTTP status code (typically 4xx or 5xx). - - `headers` - an object containing any HTTP headers where each key is a header name and value is the header content. - - `type` - a mime-type used as the content of the HTTP 'Content-Type' header (overrides `headers['Content-Type']` if present in both). - - `payload` - the formatted object used as the response payload (stringified). Can be directly manipulated but any changes will be lost - if `reformat()` is called. Any content allowed and by default includes the following content: - - `code` - the HTTP status code, derived from `error.response.code`. - - `error` - the HTTP status message (e.g. 'Bad Request', 'Internal Server Error') derived from `code`. - - `message` - the error message derived from `error.message`. -- inherited `Error` properties. - -It also supports the following method: - -- `reformat()` - rebuilds `error.response` using the other object properties. - -```javascript -var Hapi = require('hapi'); - -var handler = function () { - - var error = Hapi.error.badRequest('Cannot feed after midnight'); - error.response.code = 499; // Assign a custom error code - error.reformat(); - - this.reply(error); -}); -``` - -### Error transformation - -Error responses return a JSON object with the `code`, `error`, and `message` keys. When a different error representation is desired, such -as an HTML page or using another format, the `'onPreResponse'` extension point may be used to identify errors and replace them with a different -response object. - -```javascript -var Hapi = require('hapi'); -var server = new Hapi.Server({ views: { engines: { html: 'handlebars' } } }); - -server.ext('onPreResponse', function (request, next) { - - var response = request.response(); - if (!response.isBoom) { - return next(); - } - - // Replace error with friendly HTML - - var error = response; - var context = { - message: (error.response.code === 404 ? 'page not found' : 'something went wrong') - }; - - next(request.generateView('error', context)); -}); -``` - -#### `badRequest([message])` - -Returns an HTTP Bad Request (400) error response object with the provided `message`. - -```javascript -var Hapi = require('hapi'); -Hapi.error.badRequest('Invalid parameter value'); -``` - -#### `unauthorized(message, [scheme, [attributes]])` - -Returns an HTTP Unauthorized (401) error response object where: - -- `message` - the error message. -- `scheme` - optional HTTP authentication scheme name (e.g. `'Basic'`, `'Hawk'`). If provided, includes the HTTP 'WWW-Authenticate' - response header with the scheme and any provided `attributes`. -- `attributes` - an object where each key is an HTTP header attribute and value is the attribute content. - -```javascript -var Hapi = require('hapi'); -Hapi.error.unauthorized('Stale timestamp', 'Hawk', { ts: fresh, tsm: tsm }); -``` - -#### `unauthorized(message, wwwAuthenticate)` - -Returns an HTTP Unauthorized (401) error response object where: - -- `message` - the error message. -- `wwwAuthenticate` - an array of HTTP 'WWW-Authenticate' header responses for multiple challenges. - -```javascript -var Hapi = require('hapi'); -Hapi.error.unauthorized('Missing authentication', ['Hawk', 'Basic']); -``` - -#### `clientTimeout([message])` - -Returns an HTTP Request Timeout (408) error response object with the provided `message`. - -```javascript -var Hapi = require('hapi'); -Hapi.error.clientTimeout('This is taking too long'); -``` - -#### `serverTimeout([message])` - -Returns an HTTP Service Unavailable (503) error response object with the provided `message`. - -```javascript -var Hapi = require('hapi'); -Hapi.error.serverTimeout('Too busy, come back later'); -``` - -#### `forbidden([message])` - -Returns an HTTP Forbidden (403) error response object with the provided `message`. - -```javascript -var Hapi = require('hapi'); -Hapi.error.forbidden('Missing permissions'); -``` - -#### `notFound([message])` - -Returns an HTTP Not Found (404) error response object with the provided `message`. - -```javascript -var Hapi = require('hapi'); -Hapi.error.notFound('Wrong number'); -``` - -#### `internal([message, [data]])` - -Returns an HTTP Internal Server Error (500) error response object where: - -- `message` - the error message. -- `data` - optional data used for error logging. Typically set to the `Error` object causing the failure. - -The returned error object includes the following additional properties: - -- `data` - the `data` object provided. -- `trace` - the call stack leading to this error. If `data` is an `Error` object, `trace` is set to `data.trace`. -- `outterTrace` - If `data` is an `Error` object, set to the call stack leading to this error, otherwise `null`. - -Note that the `error.response.payload.message` is overridden with `'An internal server error occurred'` to hide any internal details from -the client. `error.message` remains unchanged. - -```javascript -var Hapi = require('hapi'); - -var handler = function () { - - var result; - try { - result = JSON.parse(request.query.value); - } - catch (err) { - result = Hapi.error.internal('Failed parsing JSON input', err); - } - - this.reply(result); -}; -``` - -#### `passThrough(code, payload, contentType, headers)` - -Returns a custom HTTP error response object where: - -- `code` - the HTTP status code (typically 4xx or 5xx). -- `payload` - the error payload string or `Buffer`. -- `contentType` - a mime-type used as the content of the HTTP 'Content-Type' header (overrides `headers['Content-Type']` if present in both). -- `headers` - an object containing any HTTP headers where each key is a header name and value is the header content. - -Used to pass-through errors received from upstream services (proxied) when a response should be treated internally as an error but contain -custom properties. - -```javascript -var Hapi = require('hapi'); -Hapi.error.passThrough(404, '

Not Found

', 'text/html', { 'Cache-Control': 'no-cache' }); -``` - -## `Hapi.Pack` - -`Pack` is a collection of servers grouped together to form a single logical unit. The pack's primary purpose is to provide a unified object -interface when working with [plugins](#plugin-interface). Grouping multiple servers into a single pack enables treating them as a single -entity which can start and stop in sync, as well as enable sharing routes and other facilities. - -The servers in a pack share the same cache. Every server belongs to a pack, even if created directed via -[`new Server()`](#new-serverhost-port-options), in which case the `server.pack` object is automatically assigned a single-server pack. - -#### `new Pack([options])` - -Creates a new `Pack` object instance where: - -- `options` - optional configuration: - - `app` - an object used to initialize the application-specific data stored in `pack.app`. - - `cache` - cache configuration as described in the server [`cache`](#server.config.cache) option. - - `requirePath` - sets the path from which node module plugins are loaded. Applies only when using `pack.require()`[#packrequirename-options-callback] - with module names that do no include a relative or absolute path (e.g. 'lout'). Defaults to the node module behaviour described in - [node modules](http://nodejs.org/api/modules.html#modules_loading_from_node_modules_folders). Note that if the modules - are located inside a 'node_modules' sub-directory, `requirePath` must end with `'/node_modules'`. - -```javascript -var Hapi = require('hapi'); -var pack = new Hapi.Pack(); -``` - -### `Pack` properties - -Each `Pack` object instance has the following properties: - -- `app` - application-specific state. Provides a safe place to store application data without potential conflicts with **hapi**. - Initialized via the pack `app` configuration option. Defaults to `{}`. -- `events` - an `Events.EventEmitter` providing a consolidate emitter of all the events emitted from all member pack servers. -- `list` - an object listing all the registered plugins where each key is a plugin name and the value is an object with: - - `name` - plugin name. - - `version` - plugin version. - - `path` - the plugin root path (where 'package.json' is located). - - `register()` - the [`exports.register()`](#exportsregisterplugin-options-next) function. - -### `Pack` methods - -#### `pack.server([host], [port], [options])` - -Creates a `Server` instance and adds it to the pack, where `host`, `port`, `options` are the same as described in -[`new Server()`](#new-serverhost-port-options) with the exception that the `cache` option is not allowed and must be -configured via the pack `cache` option. - -```javascript -var Hapi = require('hapi'); -var pack = new Hapi.Pack(); - -pack.server(8000, { labels: ['web'] }); -pack.server(8001, { labels: ['admin'] }); -``` - -#### `pack.start([callback])` - -Starts all the servers in the pack and used as described in [`server.start([callback])`](#serverstartcallback). - -```javascript -var Hapi = require('hapi'); -var pack = new Hapi.Pack(); - -pack.server(8000, { labels: ['web'] }); -pack.server(8001, { labels: ['admin'] }); - -pack.start(function () { - - console.log('All servers started'); -}); -``` - -#### `pack.stop([options], [callback])` - -Stops all the servers in the pack and used as described in [`server.stop([options], [callback])`](#serverstopoptions-callback). - -```javascript -pack.stop({ timeout: 60 * 1000 }, function () { - - console.log('All servers stopped'); -}); -``` - -#### `pack.allow(permissions)` - -Overrides the default plugin permissions when [requiring](#packrequirename-options-callback) or [registering](#packregisterplugin-options-callback) -a plugin. Where: - -- `permissions` - an object where each key is a permission name and the value is a boolean set to `true` (allow) or `false` (deny) access. - -Returns a plugin registration interface with the `pack.require()` and `pack.register()` methods. - -The default permissions are: - -- `auth` - allows registering an authentication strategy via [`plugin.auth()`](#pluginauthname-options). Defaults to `true`. -- `cache` - allows provisioning a plugin cache segment via [`plugin.cache()`](#plugincacheoptions). Defaults to `true`. -- `events` - allows access to events via [`plugin.events`](#pluginevents). Defaults to `true`. -- `ext`- allows registering extension methods via [`plugin.ext()`](#pluginextevent-method-options). Defaults to `false`. -- `helper` - allows addming server helper methods via [`plugin.helper()`](#pluginhelpername-method-options). Defaults to `true`. -- `route` - allows adding routes via [`plugin.route()`](#pluginrouteoptions). Defaults to `true`. -- `state` - allows configuring state definitions via [`plugin.state()`](#pluginstatename-options). Defaults to `true`. -- `views` - allows configuring a plugin-specific views manager via [`plugin.views()`](#pluginviewsoptions). Defaults to `true`. - -```javascript -var Hapi = require('hapi'); -var pack = new Hapi.Pack(); - -pack.server(8000, { labels: ['web'] }); -pack.server(8001, { labels: ['admin'] }); - -pack.allow({ ext: true }).require('yar', function (err) { - - if (err) { - console.log('Failed loading plugin: yar'); - } -}); -``` - -#### `pack.require(name, [options], callback)` - -Registers a plugin where: - -- `name` - the node module name as expected by node's [`require()`](http://nodejs.org/api/modules.html#modules_module_require_id). If `name` is a relative - path it is relative to the location of the file requiring it. If `name` is not a relative or absolute path (e.g. 'furball'), it is prefixed with the - value of the pack `requirePath` configuration option when present. -- `options` - optional configuration object which is passed to the plugin via the `options` argument in - [`exports.register()`](#exportsregisterplugin-options-next). If `options` is an array, the first array item is used as [`permissions`](#packallowpermissions), - and the second item is used as `options`. -- `callback` - the callback function with signature `function(err)` where: - - `err` - an error returned from `exports.register()`. Note that incorrect usage, bad configuration, missing permissions, or namespace conflicts - (e.g. among routes, helpers, state) will throw an error and will not return a callback. - -```javascript -pack.require('furball', { version: '/v' }, function (err) { - - if (err) { - console.log('Failed loading plugin: furball'); - } -}); -``` - -#### `pack.require(names, callback)` - -Registers a list of plugins where: - -- `names` - an array of plugins names as described in [`pack.require()`](#packrequirename-options-callback), or an object in which - each key is a plugin name, and each value is the `options` object used to register that plugin. If the `options` value is an array, - the first array item is used as [`permissions`](#packallowpermissions), and the second item is used as `options`. -- `callback` - the callback function with signature `function(err)` where: - - `err` - an error returned from `exports.register()`. Note that incorrect usage, bad configuration, missing permissions, or namespace conflicts - (e.g. among routes, helpers, state) will throw an error and will not return a callback. - -Batch registration is required when plugins declare a [dependency](#plugindependencydeps), so that all the required dependencies are loaded in -a single transaction (internal order does not matter). - -```javascript -pack.require(['furball', 'lout'], function (err) { - - if (err) { - console.log('Failed loading plugin: furball'); - } -}); - -pack.require({ furball: null, lout: { endpoint: '/docs' } }, function (err) { - - if (err) { - console.log('Failed loading plugins'); - } -}); -``` - -#### `pack.register(plugin, options, callback)` - -Registers a plugin object (without using `require()`) where: - -- `plugin` - the plugin object which requires: - - `name` - plugin name. - - `version` - plugin version. - - `path` - optional plugin path for resolving relative paths used by the plugin. Defaults to current working directory. - - `register()` - the [`exports.register()`](#exportsregisterplugin-options-next) function. -- `options` - optional configuration object which is passed to the plugin via the `options` argument in - [`exports.register()`](#exportsregisterplugin-options-next). If `options` is an array, the first array item is used as [`permissions`](#packallowpermissions), - and the second item is used as `options`. -- `callback` - the callback function with signature `function(err)` where: - - `err` - an error returned from `exports.register()`. Note that incorrect usage, bad configuration, missing permissions, or namespace conflicts - (e.g. among routes, helpers, state) will throw an error and will not return a callback. - -```javascript -var plug = { - name: 'test', - version: '2.0.0', - register: function (plugin, options, next) { - - plugin.route({ method: 'GET', path: '/special', handler: function () { this.reply(options.message); } } ); - next(); - } -}; - -server.pack.register(plug, { message: 'hello' }, function (err) { - - if (err) { - console.log('Failed loading plugin'); - } -}); -``` - -## `Hapi.Composer` - -The `Composer` provides a simple way to construct a [`Pack`](#hapipack) from a single configuration object, including configuring servers -and registering plugins. - -#### `new Composer(manifest)` - -Creates a `Composer` object instance where: - -- `manifest` - an object or array or objects where: - - `pack` - the pack `options` as described in [`new Pack()`](#packserverhost-port-options). - - `servers` - an array of server configuration objects where: - - `host`, `port`, `options` - the same as described in [`new Server()`](#new-serverhost-port-options) with the exception that the - `cache` option is not allowed and must be configured via the pack `cache` option. The `host` and `port` keys can be set to an environment variable by prefixing the variable name with `'$env.'`. - - `plugin` - an object where each key is a plugin name, and each value is the `options` object used to register that plugin. If the `options` - value is an array, the first array item is used as [`permissions`](#packallowpermissions), and the second item is used as `options`. - -```javascript -var Hapi = require('hapi'); - -var manifest = { - pack: { - cache: 'memory' - }, - servers: [ - { - port: 8000, - options: { - labels: ['web'] - } - }, - { - host: 'localhost', - port: 8001, - options: { - labels: ['admin'] - } - } - ], - plugins: { - 'yar': [ - { - ext: true - }, - { - cookieOptions: { - password: 'secret' - } - } - ] - } -}; - -var composer = new Hapi.Composer(manifest); -``` - -#### `composer.compose(callback)` - -Creates the packs described in the manifest construction where: - -- `callback` - the callback method, called when all packs and servers have been created and plugins registered has the signature - `function(err)` where: - - `err` - an error returned from `exports.register()`. Note that incorrect usage, bad configuration, missing permissions, or namespace conflicts - (e.g. among routes, helpers, state) will throw an error and will not return a callback. - -```javascript -composer.compose(function (err) { - - if (err) { - console.log('Failed composing'); - } -}); -``` - -#### `composer.start([callback])` - -Starts all the servers in all the pack composed where: - -- `callback` - the callback method called when all the servers have been started. - -```javascript -composer.start(function () { - - console.log('All servers started'); -}); -``` - -#### `composer.stop([options], [callback])` - -Stops all the servers in all the packs and used as described in [`server.stop([options], [callback])`](#serverstopoptions-callback). - -```javascript -pack.stop({ timeout: 60 * 1000 }, function () { - - console.log('All servers stopped'); -}); -``` - -## Plugin interface - -Plugins provide an extensibility platform for both general purpose utilities such as [batch requests](https://github.com/spumko/bassmaster) and for -application business logic. Instead of thinking about a web server as a single entity with a unified routing table, plugins enable developers to -break their application into logical units, assembled together in different combinations to fit the development, testing, and deployment needs. - -Constructing a plugin requires the following: - -- name - the plugin name is used as a unique key. Public plugins should be published in the [npm registry](https://npmjs.org) and derive their name - from the registry name. This ensures uniqueness. Private plugin names should be picked carefully to avoid conflicts with both private and public - names. Typically, private plugin names use a prefix such as the company name or an unusual combination of characters (e.g. `'--'`). When using the - [`pack.require()`](#packrequirename-options-callback) interface, the name is obtained from the 'package.json' module file. When using the - [`pack.register()`](#packregisterplugin-options-callback) interface, the name is provided as a required key in `plugin`. -- version - the plugin version is only used informatively within the framework but plays an important role in the plugin echo-system. The plugin - echo-system relies on the [npm peer dependency](http://blog.nodejs.org/2013/02/07/peer-dependencies/) functionality to ensure that plugins can - specify their dependency on a specific version of **hapi**, as well as on each other. Dependencies are expressed solely within the 'package.json' - file, and are enforced by **npm**. When using the [`pack.require()`](#packrequirename-options-callback) interface, the version is obtained from - the 'package.json' module file. When using the [`pack.register()`](#packregisterplugin-options-callback) interface, the version is provided as - a required key in `plugin`. -- `exports.register()` - the registration function described in [`exports.register()`](#exportsregisterplugin-options-next) is the plugin's core. - The function is called when the plugin is registered and it performs all the activities required by the plugin to operate. It is the single entry - point into the plugin functionality. When using the [`pack.require()`](#packrequirename-options-callback) interface, the function is obtained by - [`require()`](http://nodejs.org/api/modules.html#modules_module_require_id)'ing the plugin module and invoking the exported `register()` method. - When using the [`pack.register()`](#packregisterplugin-options-callback) interface, the function is provided as a required key in `plugin`. - -**package.json** - -```json -{ - "name": "furball", - "description": "Plugin utilities and endpoints", - "version": "0.3.0", - "main": "index", - "dependencies": { - "hoek": "0.8.x" - }, - "peerDependencies": { - "hapi": "1.x.x" - } -} -``` - -**index.js** - -```javascript -var Hoek = require('hoek'); - -var internals = { - defaults: { - version: '/version', - plugins: '/plugins' - } -}; - -internals.version = Hoek.loadPackage().version; - -exports.register = function (plugin, options, next) { - - var settings = Hoek.applyToDefaults(internals.defaults, options); - - if (settings.version) { - plugin.route({ - method: 'GET', - path: settings.version, - handler: function () { - - this.reply(internals.version); - } - }); - } - - if (settings.plugins) { - plugin.route({ - method: 'GET', - path: settings.plugins, - handler: function () { - - this.reply(listPlugins(this.server)); - } - }); - } - - var listPlugins = function (server) { - - var plugins = []; - Object.keys(server.pack.list).forEach(function (name) { - - var item = server.pack.list[name]; - plugins.push({ - name: item.name, - version: item.version - }); - }); - - return plugins; - }; - - plugin.api('plugins', listPlugins); - next(); -}; -``` - -#### `exports.register(plugin, options, next)` - -Registers the plugin where: - -- `plugin` - the registration interface representing the pack the plugin is being registered into. Provides the properties and methods listed below, based - on the permissions granted. -- `options` - the `options` object provided by the pack registration methods. -- `next` - the callback function the plugin must call to return control over to the application and complete the registration process. The function - signature is `function(err)` where: - - `err` - internal plugin error condition, which is returned back via the registration methods' callback. A plugin registration error is considered - an unrecoverable event which should terminate the application. - -```javascript -exports.register = function (plugin, options, next) { - - plugin.route({ method: 'GET', path: '/', handler: function () { this.reply('hello world') } }); - next(); -}; -``` - -### Root methods and properties - -The plugin interface root methods and properties are those available only on the `plugin` object received via the -[`exports.register()`](#exportsregisterplugin-options-next) interface. They are not available on the object received by calling -[`plugin.select()`](#pluginselectlabels). - -#### `plugin.version` - -The plugin version information. - -```javascript -exports.register = function (plugin, options, next) { - - console.log(plugin.version); - next(); -}; -``` - -#### `plugin.path` - -The plugin root path (where 'package.json' resides). - -```javascript -var Fs = require('fs'); - -exports.register = function (plugin, options, next) { - - var file = Fs.readFileSync(plugin.path + '/resources/image.png'); - next(); -}; -``` - -#### `plugin.hapi` - -A reference to the **hapi** module used to create the pack and server instances. Removes the need to add a dependency on **hapi** within the plugin. - -```javascript -exports.register = function (plugin, options, next) { - - var Hapi = plugin.hapi; - - var handler = function () { - - this.reply(Hapi.error.internal('Not implemented yet')); - }; - - plugin.route({ method: 'GET', path: '/', handler: handler }); - next(); -}; -``` - -#### `plugin.app` - -Provides access to the [common pack application-specific state](#pack-properties). - -```javascript -exports.register = function (plugin, options, next) { - - plugin.app.hapi = 'joi'; - next(); -}; -``` - -#### `plugin.events` - -_Requires the `events` plugin permission._ - -The `pack.events' emitter. - -```javascript -exports.register = function (plugin, options, next) { - - plugin.events.on('internalError', function (request, err) { - - console.log(err); - }); - - next(); -}; -``` - -#### `plugin.log(tags, [data, [timestamp]])` - -Emits a `'log'` event on the `pack.events` emitter using the same interface as [`server.log()`](#serverlogtags-data-timestamp). - -```javascript -exports.register = function (plugin, options, next) { - - plugin.log(['plugin', 'info'], 'Plugin registered'); - next(); -}; -``` - -#### `plugin.dependency(deps)` - -Declares a required dependency upon other plugins where: - -- `deps` - a single string or array of strings of plugin names which must be registered in order for this plugin to operate. Plugins listed - must be registered in the same pack transaction to allow validation of the dependency requirements. Does not provide version dependency which - should be implemented using [npm peer dependencies](http://blog.nodejs.org/2013/02/07/peer-dependencies/). - -```javascript -exports.register = function (plugin, options, next) { - - plugin.dependency('yar'); - next(); -}; -``` - -#### `plugin.views(options)` - -_Requires the `views` plugin permission._ - -Generates a plugin-specific views manager for rendering templates where: -- `options` - the views configuration as described in the server's [`views`](#server.config.views) option. Note that due to the way node - `require()` operates, plugins must require rendering engines directly and pass the engine using the `engines.module` option. - -Note that relative paths are relative to the plugin root, not the working directory or the application registering the plugin. This allows -plugin the specify their own static resources without having to require external configuration. - -```javascript -exports.register = function (plugin, options, next) { - - plugin.views({ - engines: { - jade: require('jade') - }, - path: './templates' - }); - - next(); -}; -``` - -#### `plugin.helper(name, method, [options])` - -_Requires the `helper` plugin permission._ - -Registers a server helper function with all the pack's servers as described in [`server.helper()`](#serverhelpername-method-options) - -```javascript -exports.register = function (plugin, options, next) { - - plugin.helper('user', function (id, next) { - - next({ id: id }); - }); - - next(); -}; -``` - -#### `plugin.cache(options)` - -_Requires the `cache` plugin permission._ - -Provisions a plugin cache segment within the pack's common caching facility where: - -- `options` - cache configuration as described in [**catbox** module documentation](https://github.com/spumko/catbox#policy): - - `expiresIn` - relative expiration expressed in the number of milliseconds since the item was saved in the cache. Cannot be used - together with `expiresAt`. - - `expiresAt` - time of day expressed in 24h notation using the 'MM:HH' format, at which point all cache records for the route - expire. Cannot be used together with `expiresIn`. - - `staleIn` - number of milliseconds to mark an item stored in cache as stale and reload it. Must be less than `expiresIn`. - - `staleTimeout` - number of milliseconds to wait before checking if an item is stale. - - `segment` - optional segment name, used to isolate cached items within the cache partition. Defaults to '!name' where 'name' is the - plugin name. When setting segment manually, it must begin with '!!'. - -```javascript -exports.register = function (plugin, options, next) { - - var cache = plugin.cache({ expiresIn: 60 * 60 * 1000 }); - next(); -}; -``` - -### Selectable methods and properties - -The plugin interface selectable methods and properties are those available both on the `plugin` object received via the -[`exports.register()`](#exportsregisterplugin-options-next) interface and the objects received by calling -[`plugin.select()`](#pluginselectlabels). However, unlike the root methods, they operate only on the selected subset of -servers. - -#### `plugin.select(labels)` - -Selects a subset of pack servers using the servers' `labels` configuration option where: - -- `labels` - a single string or array of strings of labels used as a logical OR statement to select all the servers with matching - labels in their configuration. - -Returns a new `plugin` interface with only access to the [selectable methods and properties](#selectable-methods-and-properties). -Selecting again on a selection operates as a logic AND statement between the individual selections. - -```javascript -exports.register = function (plugin, options, next) { - - var selection = plugin.select('web'); - selection.route({ method: 'GET', path: '/', handler: 'notfound' }); - next(); -}; -``` - -#### `plugin.length` - -The number of selected servers. - -```javascript -exports.register = function (plugin, options, next) { - - var count = plugin.length; - var selectedCount = plugin.select('web').length; - next(); -}; -``` - -#### `plugin.api(key, value)` - -Adds an plugin API to the `server.plugins[name]` ('name' of plugin) object of each selected pack server where: - -- `key` - the key assigned (`server.plugins[name][key]`). -- `value` - the value assigned. - -```javascript -exports.register = function (plugin, options, next) { - - plugin.api('util', function () { console.log('something'); }); - next(); -}; -``` - -#### `plugin.api(obj)` - -Merges a deep copy of an object into to the existing content of the `server.plugins[name]` ('name' of plugin) object of each -selected pack server where: - -- `obj` - the object merged into the API container. - -```javascript -exports.register = function (plugin, options, next) { - - plugin.api({ util: function () { console.log('something'); } }); - next(); -}; -``` - -#### `plugin.route(options)` - -_Requires the `route` plugin permission._ - -Adds a server route to the selected pack's servers as described in [`server.route(options)`](#serverrouteoptions). - -```javascript -exports.register = function (plugin, options, next) { - - var selection = plugin.select('web'); - selection.route({ method: 'GET', path: '/', handler: 'notfound' }); - next(); -}; -``` - -#### `plugin.route(routes)` - -_Requires the `route` plugin permission._ - -Adds multiple server routes to the selected pack's servers as described in [`server.route(routes)`](#serverrouteroutes). - -```javascript -exports.register = function (plugin, options, next) { - - var selection = plugin.select('admin'); - selection.routes([ - { method: 'GET', path: '/1', handler: 'notfound' }, - { method: 'GET', path: '/2', handler: 'notfound' } - ]); - - next(); -}; -``` - -#### `plugin.state(name, [options])` - -_Requires the `state` plugin permission._ - -Adds a state definition to the selected pack's servers as described in [`server.state()`](#serverstatename-options). - -```javascript -exports.register = function (plugin, options, next) { - - plugin.state('example', { encoding: 'base64' }); - next(); -}; -``` - -#### `plugin.auth(name, options)` - -_Requires the `auth` plugin permission._ - -Adds an authentication strategy to the selected pack's servers as described in [`server.auth()`](#serverauthname-options). - -```javascript -exports.register = function (plugin, options, next) { - - plugin.auth('simple', { - scheme: 'basic', - validateFunc: function (username, password, callback) { - - callback(new Error('User not found')); - } - }); - - next(); -}; -``` - -#### `plugin.ext(event, method, [options])` - -_Requires the `ext` plugin permission._ - -Adds an extension point method to the selected pack's servers as described in [`server.ext()`](#serverextevent-method-options). - -```javascript -exports.register = function (plugin, options, next) { - - plugin.ext('onRequest', function (request, extNext) { - - console.log('Received request: ' + request.path); - extNext(); - }); - - next(); -}; -``` - -## `Hapi.utils` - -An alias of the [**hoek**](https://github.com/spumko/hoek) module. - -#### `version()` - -Returns the **hapi** module version number. - -```javascript -var Hapi = require('hapi'); -console.log(Hapi.utils.version()); -``` - -## `Hapi.types` - -See [**joi** Types](https://github.com/spumko/joi#type-registry). - -## `Hapi.state` - -#### `prepareValue(name, value, options, callback)` - -Prepares a cookie value manually outside of the normal outgoing cookies processing flow. Used when decisions have to be made about -the use of cookie values when certain conditions are met (e.g. stringified object string too long). Arguments: - -- `name` - the cookie name. -- `value` - the cookie value. If no `encoding` is defined, must be a string. -- `options` - configuration override. If the state was previously registered with the server using [`server.state()`](#serverstatename-options), - the specified keys in `options` override those same keys in the server definition (but not others). -- `callback` - the callback function with signature `function(err, value)` where: - - `err` - internal error condition. - - `value` - the prepared cookie value. - -Returns the cookie value via callback without making any changes to the response. - -```javascript -var Hapi = require('hapi'); - -var handler = function (request) { - - var maxCookieSize = 512; - - var cookieOptions = { - encoding: 'iron', - password: 'secret' - }; - - var content = request.pre.user; - - Hapi.state.prepareValue('user', content, cookieOptions, function (err, value) { - - if (err) { - return request.reply(err); - } - - if (value.length < maxCookieSize) { - request.setState('user', value, { encoding: 'none' } ); // Already encoded - } - - request.reply('success'); - }); -}; -``` - diff --git a/node_modules/hapi/docs/Style.md b/node_modules/hapi/docs/Style.md deleted file mode 100755 index e57c600..0000000 --- a/node_modules/hapi/docs/Style.md +++ /dev/null @@ -1,678 +0,0 @@ -# Coding Conventions - -## JavaScript - -### Language - -#### Semicolon - - - Always end statements with `;` - ```javascript - // Right - console.log('even when not required'); - - // Wrong - console.log('even when not required') - ``` - -#### Variable declarations - - - Declare on first use, not at top of function - - Do not chain declarations unless inside `for` parentheses (repeat `var` for each variable in a separate statement) - - Give descriptive names - - Do not use similar names or synonyms for different variables unless following a convention - - `for...in` iterators should use descriptive names - - `for` iterators should use single character names - - Use combination of plural for array and singular for each item in the array - - Use camelCase, never underscores - - Avoid using numbered variables (e.g. i1, i2, i3) - -#### Scope - - - No implicit or single statement scopes - - All scopes must be wrapped in `{}` - ```javascript - // Right - - if (condition) { - return; - } - - // Wrong - - if (condition) return; - - if (condition) - return; - ``` - -#### For loops - - - Iterator variable should be declared inside the `for` parentheses, unless already defined - - Use `for` with arrays, `for...in` for objects (and always check `hasOwnProperty()`) - - When iterating over a fixed or calculated size, assign size to a variable inside the `for` declaration and use iterator variable name with `l` suffix - - Always `++i`, never `i++` - - ```javascript - // Right - - var name = 'john'; - - for (var i = 0, il = name.length; i < il; ++i) { - console.log(name[i]); - } - - // Wrong - - var position; - var name = 'john' ; - - for (position = 0; position < name.length; position++) { - console.log(name[position]) ; - } - ``` - -#### Prototype members - - - Prefix private members with `_` - ```javascript - Example.prototype.method = function () { - - this.public = 'external'; - this._private = 'internal'; - }; - ``` - - - Define `self` for passing `this` into nested functions - ```javascript - Example.prototype.method = function () { - - var self = this; - - call(123, function (err) { - - self.display(err); - }); - }; - ``` - -#### Function declaration - - - Declare functions via assignment - ``` javascript - // Right - - var method = function () { - - }; - - // Wrong - - function method() { - - } - ``` - -#### Enforcing new on Constructor - - - Use this.constructor === to check if a constructor function was called with new - ```javascript - // Right - Utils.assert(this.constructor === Server, 'Server must be instantiated using new'); - - // Wrong - Utils.assert(this instanceof Server, 'Server must be instantiated using new'); - ``` - -### Style - -#### Whitespace - - - Always spaces, never tabs - - 4 spaces indents - - No trailing whitespace at end-of-line - - ```javascript - // Right - - if (test) { - if (value === 12) { - console.log('result'); - } - } - - // Wrong - - if (test) { - if (value === 12) { - console.log('result'); - } - } - ``` - -#### String literals - - - Always `'` never `"` - ```javascript - // Right - var string = 'text in single quotes'; - - // Wrong - var string = "text in single quotes"; - ``` - -#### Newlines - - - Two empty lines between module functions or assignments (end of function to comment about next function) - ```javascript - exports.get = function () { - - // Some code - }; - // 1 - // 2 - /** - * jsDoc comment - */ - internals.utility = function () { - - //Some code - }; - ``` - - - Newline after `{` except for inlined or empty objects - - Inline an object when it improves readability and unlikely to change often - - No inline object in assignment unless empty - - ```javascript - // Right - - if (condition) { - execute(value, { strict: true }); - } - - if (condition) { - var options = { - strict: true - }; - execute(value, options); - } - - var empty = {}; - - // Wrong - - if (condition) { execute(value, { strict: true }); } - - if (condition) { - var options = { strict: true }; - execute(value, options); - } - - var empty = { - }; - ``` - - - Newline after `}` - - Only exception is when followed by `,`, `;`, `);` which must be followed by a newline - - Includes before `else`, `catch`, etc. - - Empty line after `}` if not last statement in scope - - ```javascript - // Right - - if (condition) { - value = { - func: function () { - - console.log('example'); - }, - message: 'hello' - }; - - execute(value, function (err) { - - console.log(err); - }); - } - else { - console.log('otherwise'); - } - - // Wrong - - if (condition) { - value = { - func: function () { - - console.log('example'); - }, message: 'hello' - }; - execute(value, function (err) { - - console.log(err); } - ); - } else { - console.log('otherwise'); - } - ``` - - - Empty line after `{` - - Following a multi-line condition - - In function scope declarations - - ```javascript - // Right - - exports.method = function () { - - if (condition) { - if (otherCondition) { - console.log('sometimes'); - } - - if (result && - result.code === 200) { - - console.log('special case'); - } - - console.log('always'); - } - - execute(123, function (err) { - - console.log(err); - }); - - var empty = {}; - }; - - // Wrong - - exports.method = function () { - if (condition) { - - if (otherCondition) { - - console.log('sometimes'); - } - - if (result && - result.code === 200) { - console.log('special case'); - } - - console.log('always'); - } - - execute(123, function (err) { - console.log(err); - }); - - var empty = { - }; - }; - ``` - - - No empty line before end of scope - ```javascript - // Right - - if (condition) { - if (otherCondition) { - console.log('done'); - } - } - - // Wrong - - if (condition) { - if (otherCondition) { - console.log('done'); - - } - - } - ``` - -#### Spaces - - - Use one and only one space (when required) - ```javascript - // Right - var value = calculate(1, 3); - - // Wrong - var value = calculate(1, 3); - ``` - - - No space between function name and `(` - ```javascript - // Right - - function example() { - - return value; - } - - var key = example(); - - // Wrong - - function example () { - - return value; - } - - var key = example (); - ``` - - - No space after `(` or before `)` - ```javascript - // Right - - execute('order', 34); - - if (result === 'ok') { - console.log('success'); - } - - // Wrong - - execute( 'order', 34 ); - - if ( result === 'ok' ) { - console.log( 'success' ); - } - ``` - - - No space before object key `:`, always after object key `:` - ```javascript - // Right - - var obj = { - a: 1, - b: 2, - c: 3 - }; - - // Wrong - - var obj = { - a : 1, - b :2, - c:3 - }; - ``` - - - No space before `;`, always after `;` if not end-of-line - ```javascript - // Right - - var name = 'john'; - - for (var i = 0, il = name.length; i < il; ++i) { - console.log(name[i]); - } - - // Wrong - - var name = 'john' ; - - for (var i = 0, il = name.length;i < il ;++i) { - console.log(name[i]) ; - } - ``` - - - Always space after reserved keywords (`if`, `else`, `for`, `return`, `function`, etc.) - ```javascript - // Right - - for (var book in books) { - if (books.hasOwnProperty(book)) { - console.log(book.name); - } - } - - // Wrong - - for(var book in books) { - if(books.hasOwnProperty(book)) { - console.log(book.name); - } - } - ``` - - - Always space after `{` and before `}` in inlined object - - No space for empty objects `{}` - - One space for empty functions `{ }` - - ```javascript - // Right - - var user = { name: 'john', email: 'john@example.com' }; - var empty = {}; - var callback = function () { }; - - // Wrong - - var user = {name: 'john', email: 'john@example.com'}; - var empty = { }; - var callback = function () {}; - ``` - - - No space after `[` and before `]` in inlined arrays - ```javascript - // Right - var numbers = [1, 2, 3]; - - // Wrong - var numbers = [ 1, 2, 3 ]; - ``` - - - Always space after `//` - ```javascript - // Right - // Some comment - - // Wrong - //Some comment - ``` - - - No space before `,`, always after `,` unless end-of-line - ```javascript - // Right - - var numbers = [1, 2, 3]; - var user = { name: 'john', email: 'john@example.com' }; - - for (var i = 0, il = name.length; i < il; ++i) { - console.log(name[i]); - } - - // Wrong - - var numbers = [1,2 ,3]; - var user = { name: 'john',email: 'john@example.com' }; - - for (var i = 0,il = name.length; i < il; ++i) { - console.log(name[i]); - } - ``` - - - Always space before and after operators, unless following ident or end-of-line - - ```javascript - // Right - - var a = 1 + 3; - var b = 'john' + - ' ' + - 'doe'; - - // Wrong - - var a=1+3; - var b='john'+ - ' '+ - 'doe'; - ``` - -#### Commas - - - Never begin a line with `,` (always at the end of the previous line) - ```javascript - // Right - execute('some error message', - 12345, - this); - - // Wrong - execute('some error message' - ,12345 - ,this); - ``` - -#### Operators - - - Never begin a line with an operator (always at the end of the previous line) - ```javascript - // Right - - var message = 'Hello ' + - 'Steve, ' + - 'How are you?'; - - if (value === 'hello' && - result === 'ok') { - - console.log('yes'); - } - - // Wrong - - var message = 'Hello ' - + 'Steve, ' - + 'How are you?'; - - if (value === 'hello' - && result === 'ok') { - - console.log('yes'); - } - ``` - -#### Comments - - - Always use `//` unless it's a jsDoc declaration or license header - - Always begin sentences with an upper case - - No trailing `.` unless comment contains multiple sentences - - Formal style, consistent voice, no humor, present tense - - No developer name or other personal notes - - No TODOs - - - Line - - Provides narrative for the following single code line (or single statement broken for readability) - - One line of comment only - - One empty line before and none after the comment line - - No empty line before when following `{` unless other rules require it - - ```javascript - function execute() { - - // Initialize state - var position = 0; - - if (condition) { - // Return message - return 'hello'; - } - } - ``` - - - Segment - - Provides narrative for the following code section (one or more lines of code, with or without line breaks) - - One or more lines of comments - - One empty line before and one after comments block - - ```javascript - function execute() { - - // Print each book's name - - for (var book in books) { - - // Check for valid properties - - if (books.hasOwnProperty(book)) { - console.log(book.name); - } - } - } - ``` - - - Note - - Explains the behaviour of a single code statement (can be broken into multiple lines) - - Used to document unexpected behaviour or non-standard practice - - Appears immediately at the end of the line (or statement) it describes, following whitespace to separate it from code block - - ```javascript - function execute(value) { - - if (value !== null && - value !== undefined) { // Explicit check as 'value' can be 0 - - console.log(value); - } - } - ``` - -#### Multi-line statements - - - Statements should only be broken into multiple lines to improve readability - - Break statements if they are longer than 150 characters long - - No empty lines in the middle of a single statement - - Indent multi-line statements - - - Conditions should be indented to the first character of the condition in the first line - - ```javascript - if (result && - result.status && - result.status.code === 200) { - - console.log('success'); - } - ``` - - - Variable should be indented to the first character of the value in the first line - ```javascript - var message = "hello" + - " and welcome"; - ``` - -## Node - -### Require - - - Use uppercase variable names for imported modules - - All require statements must be declared at the top of the module - - Always use relative paths - -### Module globals - - - Every module can only have two top level globals: - - `exports` - defined automatically by node - - `internals` - must be declared as an object at the top of each module immediate following the `require` section - - Any variable global to the module must be a property of `internals`, including constants - - If a module has automatically executing code, it must be contained within a function (using the `internals` namespace) and called at the top of the module after the `internals` declaration - -### Variable names - - - `err` is reserved for errors received via a callback. Use `error` for local function variables. - -### Callback - - - First argument must always be `err` - - If a function takes a `callback` argument, it **must** be called on `process.nextTick()`. Otherwise, the argument name **must** be `next` to clearly declare that it may get called on same tick. diff --git a/node_modules/hapi/examples/auth.js b/node_modules/hapi/examples/auth.js deleted file mode 100755 index 51cc234..0000000 --- a/node_modules/hapi/examples/auth.js +++ /dev/null @@ -1,102 +0,0 @@ -// Load modules - -var Hawk = require('hawk'); -var Bcrypt = require('bcrypt'); -var Hapi = require('../lib'); - - -// Declare internals - -var internals = {}; - - -internals.users = { - john: { - user: 'john' - } -}; - - -internals.passwords = { - john: '$2a$10$iqJSHD.BGr0E2IxQwYgJmeP3NvhPrXAeLSaGCj6IR/XU5QtjVu5Tm' // password: secret -}; - - -internals.credentials = { - 'john': { - id: 'john', - key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', - algorithm: 'sha256' - } -}; - - -internals.validate = function (username, password, callback) { - - Bcrypt.compare(password, internals.passwords[username], function (err, isValid) { - - callback(null, isValid , internals.users[username]); - }); -}; - - -internals.getCredentials = function (id, callback) { - - callback(null, internals.credentials[id]); -}; - - -internals.hawkHeader = function (id, path, server) { - - if (internals.credentials[id]) { - return Hawk.client.header(server.info.uri + path, 'GET', { credentials: internals.credentials[id] }).field; - } - else { - return ''; - } -}; - -internals.handler = function (request) { - - request.reply('Success'); -}; - - -internals.main = function () { - - var config = { - auth: { - 'hawk': { - scheme: 'hawk', - getCredentialsFunc: internals.getCredentials - }, - 'basic': { - scheme: 'basic', - validateFunc: internals.validate - } - } - }; - - var server = new Hapi.Server(8000, config); - - server.route([ - { method: 'GET', path: '/basic', config: { handler: internals.handler, auth: { strategies: ['basic'] } } }, - { method: 'GET', path: '/hawk', config: { handler: internals.handler, auth: { strategies: ['hawk'] } } }, - { method: 'GET', path: '/multiple', config: { handler: internals.handler, auth: { strategies: ['basic', 'hawk'] } } } - ]); - - server.start(function () { - - console.log('\nBasic request to /basic:'); - console.log('curl ' + server.info.uri + '/basic -H "Authorization: Basic ' + (new Buffer('john:secret', 'utf8')).toString('base64') + '"'); - console.log('\nHawk request to /hawk:'); - console.log('curl ' + server.info.uri + '/hawk -H \'Authorization: ' + internals.hawkHeader('john', '/hawk', server) + '\''); - console.log('\nBasic request to /multiple:'); - console.log('curl ' + server.info.uri + '/multiple -H "Authorization: Basic ' + (new Buffer('john:secret', 'utf8')).toString('base64') + '"'); - console.log('\nHawk request to /multiple:'); - console.log('curl ' + server.info.uri + '/multiple -H \'Authorization: ' + internals.hawkHeader('john', '/multiple', server) + '\''); - }); -}; - - -internals.main(); \ No newline at end of file diff --git a/node_modules/hapi/examples/cache.js b/node_modules/hapi/examples/cache.js deleted file mode 100755 index 88f4b3f..0000000 --- a/node_modules/hapi/examples/cache.js +++ /dev/null @@ -1,64 +0,0 @@ -// Load modules - -var Hapi = require('../lib'); - - -// Declare internals - -var internals = {}; - - -internals.profile = function () { - - this.reply({ - 'id': 'fa0dbda9b1b', - 'name': 'John Doe' - }); -}; - - -internals.activeItem = function () { - - this.reply({ - 'id': '55cf687663', - 'name': 'Active Item' - }); -}; - - -internals.item = function () { - - setTimeout(function () { - - this.reply({ - 'id': this.params.id, - 'name': 'Item' - }); - }, 600); -}; - - -internals.main = function () { - - var config = { - cache: { - engine: 'redis', - host: '127.0.0.1', - port: 6379 - } - }; - - var server = new Hapi.Server(8000, config); - - server.route([ - { method: 'GET', path: '/profile', config: { handler: internals.profile, cache: { expiresIn: 30000 } } }, - { method: 'GET', path: '/item', config: { handler: internals.activeItem } }, - { method: 'GET', path: '/item/{id}', config: { handler: internals.item, cache: { mode: 'server', expiresIn: 20000, staleIn: 10000, staleTimeout: 500 } } } - ]); - - server.start(); -}; - - -internals.main(); - diff --git a/node_modules/hapi/examples/composer.json b/node_modules/hapi/examples/composer.json deleted file mode 100755 index 01f850f..0000000 --- a/node_modules/hapi/examples/composer.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "pack": { - "cache": "redis" - }, - "servers": [ - { - "host": "localhost", - "port": 8000, - "options": { - "labels": ["api", "nasty"] - } - }, - { - "port": 8001, - "options": { - "labels": ["api", "nice"] - } - } - ], - "plugins": { - "furball": { - "version": false, - "plugins": "/" - } - } -} diff --git a/node_modules/hapi/examples/cookie.js b/node_modules/hapi/examples/cookie.js deleted file mode 100755 index 74e70bf..0000000 --- a/node_modules/hapi/examples/cookie.js +++ /dev/null @@ -1,94 +0,0 @@ -// Load modules - -var Hapi = require('../lib'); - - -// Declare internals - -var internals = {}; - - -internals.users = { - john: { - id: 'john', - password: 'password', - name: 'John Doe' - } -}; - - -internals.home = function () { - - this.reply('Login page

Welcome ' + this.auth.credentials.name + '!


'); -}; - - -internals.login = function () { - - if (this.auth.isAuthenticated) { - return this.reply.redirect('/'); - } - - var message = ''; - var account = null; - - if (this.method === 'post') { - - if (!this.payload.username || - !this.payload.password) { - - message = 'Missing username or password'; - } - else { - account = internals.users[this.payload.username]; - if (!account || - account.password !== this.payload.password) { - - message = 'Invalid username or password'; - } - } - } - - if (this.method === 'get' || - message) { - - return this.reply('Login page' + (message ? '

' + message + '


' : '') + '
Username:
Password:
'); - } - - this.auth.session.set(account); - return this.reply.redirect('/'); -}; - - -internals.logout = function () { - - this.auth.session.clear(); - return this.reply.redirect('/'); -}; - - -internals.main = function () { - - var config = { - auth: { - scheme: 'cookie', - password: 'secret', - cookie: 'sid-example', - redirectTo: '/login', - isSecure: false - } - }; - - var server = new Hapi.Server('localhost', 8000, config); - - server.route([ - { method: 'GET', path: '/', config: { handler: internals.home, auth: true } }, - { method: '*', path: '/login', config: { handler: internals.login, auth: { mode: 'try' } } }, - { method: 'GET', path: '/logout', config: { handler: internals.logout, auth: true } } - ]); - - server.start(); -}; - - -internals.main(); \ No newline at end of file diff --git a/node_modules/hapi/examples/directory/index.html b/node_modules/hapi/examples/directory/index.html deleted file mode 100755 index ae8a2f0..0000000 --- a/node_modules/hapi/examples/directory/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - Served with static directory routing - - -

- Welcome to - -

- - \ No newline at end of file diff --git a/node_modules/hapi/examples/directory/server.js b/node_modules/hapi/examples/directory/server.js deleted file mode 100755 index 36dbaa0..0000000 --- a/node_modules/hapi/examples/directory/server.js +++ /dev/null @@ -1,32 +0,0 @@ -// Load modules - -var Hapi = require('../../lib'); - - -// Declare internals - -var internals = {}; - - -internals.serveImages = function (request) { - - return '../../images/'; -}; - - -internals.main = function () { - - var server = new Hapi.Server(8000, { files: { relativeTo: 'routes' } }); - - server.route([ - { method: 'GET', path: '/img/{path}', handler: { directory: { path: internals.serveImages } } }, - { method: 'GET', path: '/files/{path*}', handler: { directory: { path: '../../', listing: true, redirectToSlash: true } } }, - { method: 'GET', path: '/{path?}', handler: { directory: { path: './' } } } - ]); - - server.start(); -}; - - -internals.main(); - diff --git a/node_modules/hapi/examples/errors.js b/node_modules/hapi/examples/errors.js deleted file mode 100755 index 39ec0f7..0000000 --- a/node_modules/hapi/examples/errors.js +++ /dev/null @@ -1,42 +0,0 @@ -// Load modules - -var Hapi = require('../lib'); - - -// Declare internals - -var internals = {}; - - -internals.get = function () { - - this.reply(new Error('Here is my error')); -}; - - -internals.onPreResponse = function (request, next) { - - // Demonstrates how to hide error messages from the client - - if (request.response().isBoom) { - var error = request.response(); - error.response.payload.message = 'Censored Error'; - } - - next(); -}; - - -internals.main = function () { - - var server = new Hapi.Server(8000); - - server.ext('onPreResponse', internals.onPreResponse); - - server.route({ method: 'GET', path: '/', handler: internals.get }); - server.start(); -}; - - -internals.main(); - diff --git a/node_modules/hapi/examples/extensions.js b/node_modules/hapi/examples/extensions.js deleted file mode 100755 index 5ca8dba..0000000 --- a/node_modules/hapi/examples/extensions.js +++ /dev/null @@ -1,59 +0,0 @@ -// Load modules - -var Hapi = require('../lib'); - - -// Declare internals - -var internals = {}; - - -internals.get = function (request) { - - request.reply('Success!\n'); -}; - - -internals.onRequest = function (request, next) { - - console.log('onRequest'); - next(); -}; - - -internals.onPreHandler1 = function (request, next) { - - console.log('onPreHandler1: ' + request.method); - next(); -}; - - -internals.onPreHandler2 = function (request, next) { - - console.log('onPreHandler2: ' + request.path); - next(); -}; - - -internals.onPostHandler = function (request, next) { - - console.log('onPostHandler'); - next(); -}; - - -internals.main = function () { - - var server = new Hapi.Server(8000); - - server.ext('onRequest', internals.onRequest); // New request, before handing over to the router (allows changes to method and url) - server.ext('onPreHandler', [internals.onPreHandler1, internals.onPreHandler2]); // After validation and body parsing, before route handler - server.ext('onPostHandler', internals.onPostHandler); // After route handler returns, before setting response - - server.route({ method: 'GET', path: '/', handler: internals.get }); - server.start(); -}; - - -internals.main(); - diff --git a/node_modules/hapi/examples/favicon.ico b/node_modules/hapi/examples/favicon.ico deleted file mode 100644 index 28e95e37258c0e82c5b8385265f6410f57a93016..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1150 zcmZQzU<5(|0R|wcz>vYhz#zuJz@P!dKp~(AL>x#lFaYJy!T>s+y7MQBGyM`=Yx zMccf2^AZ*;SP%Y&D(cX7pz#9d-}{-t6#rO^4>OgJ>g&iLs-vuCA^Um^?7tWMS+dKYp-%`t*tC$&)9Nr%s(RhKcV#b}XxE z(&YaIO-=WnK6@qwliRazzwgVJFQs7WU^K{WKsUv~_*?evZ>gOz^M7(>)qkIeh{yX6 z9&$f>_MB-#PR@hHt2Q^n)ZwB}oIM*=+}-m(v~l|XfV`^z_J00 - - - Served with static file routing - - -

- Welcome to - -

- - \ No newline at end of file diff --git a/node_modules/hapi/examples/file/server.js b/node_modules/hapi/examples/file/server.js deleted file mode 100755 index fd86d74..0000000 --- a/node_modules/hapi/examples/file/server.js +++ /dev/null @@ -1,31 +0,0 @@ -// Load modules - -var Hapi = require('../../lib'); - - -// Declare internals - -var internals = {}; - - -internals.serveLogo = function (request) { - - request.reply(new Hapi.response.File('../../images/hapi.png')); -}; - - -internals.main = function () { - - var http = new Hapi.Server(8080); - - http.route([ - { method: 'GET', path: '/', handler: { file: './index.html' } }, - { method: 'GET', path: '/img/logo.jpg', handler: internals.serveLogo } - ]); - - http.start(); -}; - - -internals.main(); - diff --git a/node_modules/hapi/examples/files.js b/node_modules/hapi/examples/files.js deleted file mode 100755 index b209e3d..0000000 --- a/node_modules/hapi/examples/files.js +++ /dev/null @@ -1,31 +0,0 @@ -// Load modules - -var Hapi = require('../lib'); - - -// Declare internals - -var internals = {}; - - -internals.main = function () { - - var server = new Hapi.Server(8000); - - var filePath = function (request) { - - return './' + request.params.file + '.js'; - }; - - server.route([ - { method: 'GET', path: '/favicon.ico', handler: { file: './favicon.ico' } }, - { method: 'GET', path: '/download', handler: { file: { path: './favicon.ico', mode: 'attachment' } } }, - { method: 'GET', path: '/source/{file}', handler: { file: filePath } } - ]); - - server.start(); -}; - - -internals.main(); - diff --git a/node_modules/hapi/examples/helpers.js b/node_modules/hapi/examples/helpers.js deleted file mode 100755 index 335015c..0000000 --- a/node_modules/hapi/examples/helpers.js +++ /dev/null @@ -1,63 +0,0 @@ -// Load modules - -var Hapi = require('../lib'); - - -// Declare internals - -var internals = { - gen: 0 -}; - - -internals.user = function (id, next) { - - setTimeout(function () { - - return next({ id: id, gen: ++internals.gen }); - }, 110); -}; - - -internals.main = function () { - - var server = new Hapi.Server(8000); - - server.helper('user', internals.user, { cache: { expiresIn: 2000, staleIn: 1000, staleTimeout: 100 } }); - server.start(function () { - - server.helpers.user('john', function (result1) { - - console.log(result1); // Gen: 1 - - setTimeout(function () { - - server.helpers.user('john', function (result2) { - - console.log(result2); // Gen: 1 - - setTimeout(function () { - - server.helpers.user('john', function (result3) { - - console.log(result3); // Gen: 1 - - setTimeout(function () { - - server.helpers.user('john', function (result4) { - - console.log(result4); // Gen: 2 - server.stop(); - }); - }, 50); - }); - }, 1010); - }); - }, 50); - }); - }); -}; - - -internals.main(); - diff --git a/node_modules/hapi/examples/injection.js b/node_modules/hapi/examples/injection.js deleted file mode 100755 index 2ec58b8..0000000 --- a/node_modules/hapi/examples/injection.js +++ /dev/null @@ -1,37 +0,0 @@ -// Load modules - -var Hapi = require('../lib'); - - -// Declare internals - -var internals = {}; - - -internals.get = function () { - - this.reply('Success!'); -}; - - -internals.main = function () { - - var server = new Hapi.Server(8000); - server.route({ method: 'GET', path: '/', handler: internals.get }); - - // Create request - - var req = { - method: 'get', - url: '/' - }; - - server.inject(req, function (res) { - - console.log(res.result); - }); -}; - - -internals.main(); - diff --git a/node_modules/hapi/examples/jsonp.js b/node_modules/hapi/examples/jsonp.js deleted file mode 100755 index 8664702..0000000 --- a/node_modules/hapi/examples/jsonp.js +++ /dev/null @@ -1,30 +0,0 @@ -// Load modules - -var Hapi = require('../lib'); - - -// Declare internals - -var internals = {}; - - -internals.main = function () { - - var server = new Hapi.Server(8000); - - var handler = function () { - - console.log(this.raw.req.headers); - var parts = this.params.name.split('/'); - this.reply({ first: parts[0], last: parts[1] }); - }; - - server.route({ method: 'GET', path: '/user/{name*2}', config: { handler: handler, jsonp: 'callback' } }); - server.start(function () { - - console.log('Try: http://localhost:8000/user/1/2?callback=docall'); - }); -}; - - -internals.main(); diff --git a/node_modules/hapi/examples/prerequisites.js b/node_modules/hapi/examples/prerequisites.js deleted file mode 100755 index 7982604..0000000 --- a/node_modules/hapi/examples/prerequisites.js +++ /dev/null @@ -1,74 +0,0 @@ -// Load modules - -var Hapi = require('../lib'); - - -// Declare internals - -var internals = {}; - - -internals.fetch1 = function (request, next) { - - next('Hello'); -}; - - -internals.fetch2 = function (request, next) { - - next(request.pre.m1 + request.pre.m3 + request.pre.m4); -}; - - -internals.fetch3 = function (request, next) { - - setTimeout(function () { - - next(' '); - }, 1000); -}; - - -internals.fetch4 = function (request, next) { - - next('World'); -}; - - -internals.fetch5 = function (request, next) { - - next(request.pre.m2 + '!'); -}; - - -internals.get = function (request) { - - request.reply(request.pre.m5 + '\n'); -}; - - -internals.main = function () { - - var server = new Hapi.Server(8000); - - server.route({ - method: 'GET', - path: '/', - config: { - pre: [ - { method: internals.fetch1, assign: 'm1', mode: 'parallel' }, - { method: internals.fetch2, assign: 'm2' }, - { method: internals.fetch3, assign: 'm3', mode: 'parallel' }, - { method: internals.fetch4, assign: 'm4', mode: 'parallel' }, - { method: internals.fetch5, assign: 'm5' } - ], - handler: internals.get - } - }); - - server.start(); -}; - - -internals.main(); - diff --git a/node_modules/hapi/examples/proxy.js b/node_modules/hapi/examples/proxy.js deleted file mode 100755 index 6fcfed3..0000000 --- a/node_modules/hapi/examples/proxy.js +++ /dev/null @@ -1,26 +0,0 @@ -// Load modules - -var Hapi = require('../lib'); - - -// Declare internals - -var internals = {}; - - -internals.main = function () { - - var server = new Hapi.Server(8000); - - var mapper = function (request, callback) { - - callback(null, 'http://www.google.com/search?q=' + request.params.term); - }; - - server.route({ method: '*', path: '/{p*}', handler: { proxy: { host: 'google.com', port: 80, redirects: 5 } } }); - server.route({ method: 'GET', path: '/hapi/{term}', handler: { proxy: { mapUri: mapper } } }); - server.start(); -}; - - -internals.main(); diff --git a/node_modules/hapi/examples/socketio.js b/node_modules/hapi/examples/socketio.js deleted file mode 100755 index 34fd2d3..0000000 --- a/node_modules/hapi/examples/socketio.js +++ /dev/null @@ -1,38 +0,0 @@ -// The following initializes a socket.io server. -// The socket.io client JavaScript is located at http://localhost:8080/socket.io/socket.io.js -// To create a new socket.io handshake make a POST request to http://localhost:8080/socket.io/1 -// use the resulting session ID for subsequent requests (see https://github.com/LearnBoost/socket.io-spec) -// For example, in the chrome debug console you can create a new WebSocket with the following URI -// 'ws://localhost:8080/socket.io/1/websocket/Ww4ULq6wOTUZYD62v3yu' -// where Ww4ULq6wOTUZYD62v3yu is the session ID - -// Load modules - -var Hapi = require('../'); -var SocketIO = require('socket.io'); - - -// Declare internals - -var internals = {}; - - -internals.startServer = function () { - - var server = new Hapi.Server(8000); - - var helloHandler = function () { - - this.reply('Hello'); - }; - - server.route({ method: 'GET', path: '/', handler: helloHandler }); - - server.start(function () { - - var io = SocketIO.listen(server.listener); - }); -}; - - -internals.startServer(); \ No newline at end of file diff --git a/node_modules/hapi/examples/stream.js b/node_modules/hapi/examples/stream.js deleted file mode 100755 index a2566a2..0000000 --- a/node_modules/hapi/examples/stream.js +++ /dev/null @@ -1,35 +0,0 @@ -// Load modules - -var Hapi = require('../lib'); -var Request = require('request'); - - -// Declare internals - -var internals = {}; - - -internals.echo = function () { - - this.reply(this.raw.req); -}; - - -internals.request = function () { - - var reqStream = Request('http://google.com'); - reqStream.once('response', this.reply); -}; - - -internals.main = function () { - - var server = new Hapi.Server(8000); - server.route({ method: 'POST', path: '/', config: { handler: internals.echo, payload: 'stream' } }); - server.route({ method: 'GET', path: '/request', handler: internals.request }); - server.start(); -}; - - -internals.main(); - diff --git a/node_modules/hapi/examples/tails.js b/node_modules/hapi/examples/tails.js deleted file mode 100755 index 91c915f..0000000 --- a/node_modules/hapi/examples/tails.js +++ /dev/null @@ -1,47 +0,0 @@ -// Load modules - -var Hapi = require('../lib'); - - -// Declare internals - -var internals = {}; - - -internals.get = function () { - - var tail1 = this.tail('tail1'); - setTimeout(function () { - - console.log(1); - tail1(); - }, 5000); - - var tail2 = this.tail('tail2'); - setTimeout(function () { - - console.log(2); - tail2(); - }, 2000); - - this.reply('Success!\n'); -}; - - -internals.main = function () { - - var server = new Hapi.Server(8000); - server.route({ method: 'GET', path: '/', handler: internals.get }); - server.start(); - - // Listen to tail events - - server.on('tail', function (request) { - - console.log('Wag the dog'); - }); -}; - - -internals.main(); - diff --git a/node_modules/hapi/examples/validation.js b/node_modules/hapi/examples/validation.js deleted file mode 100755 index 868e833..0000000 --- a/node_modules/hapi/examples/validation.js +++ /dev/null @@ -1,69 +0,0 @@ -// Load modules - -var Hapi = require('../lib'); - - -// Declare internals - -var internals = {}; - - -// Type shortcuts - -var S = Hapi.types.String; -var N = Hapi.types.Number; -var A = Hapi.types.Array; - - -internals.get = function () { - - this.reply('Success!\n'); -}; - - -internals.payload = function () { - - this.reply('Success!\n'); -}; - - -internals.main = function () { - - var server = new Hapi.Server(8000); - - server.route([ - { method: 'GET', path: '/', config: { handler: internals.get, validate: { query: { username: S() } } } }, - { method: 'GET', path: '/admin', config: { handler: internals.get, validate: { query: { username: S().required().with('password'), password: S() } } } }, - { method: 'GET', path: '/users', config: { handler: internals.get, validate: { query: { email: S().email().required().min(18) } } } }, - { method: 'GET', path: '/config', config: { handler: internals.get, validate: { query: { choices: A().required() } } } }, - { method: 'GET', path: '/test', config: { handler: internals.get, validate: { query: { num: N().min(0) } } } }, - { method: 'GET', path: '/test2', config: { handler: internals.get, validate: { query: { p1: S().required().rename('itemId') } } } }, - { method: 'GET', path: '/simple', config: { handler: internals.get, validate: { query: { input: S().min(3) } } } } - ]); - - var schema = { - title: S(), - status: S().valid('open', 'pending', 'close'), - participants: A().includes(S(), N()) - }; - - server.route({ method: 'POST', path: '/users/{id}', config: { handler: internals.payload, validate: { query: {}, payload: schema } } }); - - server.start(); -}; - - -internals.main(); - -/* - Try various URLs like: - http://localhost:8000/ // success - http://localhost:8000/?username=test // success - http://localhost:8000/admin?username=steve&password=shhhhhh // success - http://localhost:8000/admin?username=steve // fail - http://localhost:8000/users?email=steve@example.com // success - http://localhost:8000/users?email=@example.com // fail - http://localhost:8000/config?choices=1&choices=2 // success - http://localhost:8000/config?choices=1 // success - http://localhost:8000/config // fail -*/ diff --git a/node_modules/hapi/examples/views/cms/_pages/.placeholder b/node_modules/hapi/examples/views/cms/_pages/.placeholder deleted file mode 100755 index e69de29..0000000 diff --git a/node_modules/hapi/examples/views/cms/_pages/Test b/node_modules/hapi/examples/views/cms/_pages/Test deleted file mode 100644 index 93a5f6a..0000000 --- a/node_modules/hapi/examples/views/cms/_pages/Test +++ /dev/null @@ -1 +0,0 @@ -123123 \ No newline at end of file diff --git a/node_modules/hapi/examples/views/cms/pages.js b/node_modules/hapi/examples/views/cms/pages.js deleted file mode 100755 index e9b0c52..0000000 --- a/node_modules/hapi/examples/views/cms/pages.js +++ /dev/null @@ -1,65 +0,0 @@ -// Load modules - -var Fs = require('fs'); -var Path = require('path'); - - -// Declare internals - -var internals = {}; - - -internals.Pages = function (dirPath) { - - this._dirPath = dirPath; - this._cache = {}; - this.loadPagesIntoCache(); -}; - - -internals.Pages.prototype.loadPagesIntoCache = function () { - - var self = this; - Fs.readdirSync(this._dirPath).forEach(function (file) { - - if (file[0] !== '.') { - self._cache[file] = self.loadPageFile(file); - } - }); -}; - - -internals.Pages.prototype.getAll = function () { - - return this._cache; -}; - - -internals.Pages.prototype.getPage = function (name) { - - return this._cache[name]; -}; - - -internals.Pages.prototype.savePage = function (name, contents) { - - name = Path.normalize(name); - Fs.writeFileSync(Path.join(this._dirPath, name), contents); - this._cache[name] = { - name: name, - contents: contents - }; -}; - - -internals.Pages.prototype.loadPageFile = function (file) { - - var contents = Fs.readFileSync(Path.join(this._dirPath, file)); - - return { - name: file, - contents: contents.toString() - }; -}; - -module.exports = new internals.Pages(Path.join(__dirname, '_pages')); \ No newline at end of file diff --git a/node_modules/hapi/examples/views/cms/server.js b/node_modules/hapi/examples/views/cms/server.js deleted file mode 100755 index ba8f0a6..0000000 --- a/node_modules/hapi/examples/views/cms/server.js +++ /dev/null @@ -1,81 +0,0 @@ -// Load modules - -var Path = require('path'); -var Hapi = require('../../../'); -var Pages = require('./pages'); - - -// Declare internals - -var internals = {}; - - -var view = function (viewName) { - - return function (request) { - - request.reply.view(viewName, { title: viewName }); - }; -}; - - -var getPages = function (request) { - - request.reply.view('index', { pages: Object.keys(Pages.getAll()), title: 'All pages' }); -}; - - -var getPage = function (request) { - - request.reply.view('page', { page: Pages.getPage(request.params.page), title: request.params.page }); -}; - - -var createPage = function (request) { - - Pages.savePage(request.payload.name, request.payload.contents); - request.reply.view('page', { page: Pages.getPage(request.payload.name), title: 'Create page' }); -}; - - -var showEditForm = function (request) { - - request.reply.view('edit', { page: Pages.getPage(request.params.page), title: 'Edit: ' + request.params.page }); -}; - - -var updatePage = function (request) { - - Pages.savePage(request.params.page, request.payload.contents); - request.reply.view('page', { page: Pages.getPage(request.params.page), title: request.params.page }); -}; - -internals.main = function () { - - var options = { - views: { - engines: { html: 'handlebars' }, - path: Path.join(__dirname, 'views'), - layout: true, - partialsPath: Path.join(__dirname, 'views', 'partials') - }, - state: { - cookies: { - failAction: 'ignore' - } - } - }; - - var server = new Hapi.Server(8000, options); - server.route({ method: 'GET', path: '/', handler: getPages }); - server.route({ method: 'GET', path: '/pages/{page}', handler: getPage }); - server.route({ method: 'GET', path: '/create', handler: view('create') }); - server.route({ method: 'POST', path: '/create', handler: createPage }); - server.route({ method: 'GET', path: '/pages/{page}/edit', handler: showEditForm }); - server.route({ method: 'POST', path: '/pages/{page}/edit', handler: updatePage }); - server.start(); -}; - - -internals.main(); - diff --git a/node_modules/hapi/examples/views/cms/views/create.html b/node_modules/hapi/examples/views/cms/views/create.html deleted file mode 100755 index ed519f0..0000000 --- a/node_modules/hapi/examples/views/cms/views/create.html +++ /dev/null @@ -1,25 +0,0 @@ -
-
-
- - -
-
- - -
-
- - Cancel -
-
-
- - - \ No newline at end of file diff --git a/node_modules/hapi/examples/views/cms/views/edit.html b/node_modules/hapi/examples/views/cms/views/edit.html deleted file mode 100755 index 5b780ff..0000000 --- a/node_modules/hapi/examples/views/cms/views/edit.html +++ /dev/null @@ -1,25 +0,0 @@ -
-
-
- - -
-
- - -
-
- - Cancel -
-
-
- - - \ No newline at end of file diff --git a/node_modules/hapi/examples/views/cms/views/index.html b/node_modules/hapi/examples/views/cms/views/index.html deleted file mode 100755 index b12f5a8..0000000 --- a/node_modules/hapi/examples/views/cms/views/index.html +++ /dev/null @@ -1,34 +0,0 @@ -{{#if pages}} -

Sitemap

-
    - {{#each pages}} -
  • {{this}}

  • - {{/each}} -
-{{else}} -
- Create a page -
-
- - -
-
- - -
-
- -
-
-
- - - -{{/if}} \ No newline at end of file diff --git a/node_modules/hapi/examples/views/cms/views/layout.html b/node_modules/hapi/examples/views/cms/views/layout.html deleted file mode 100755 index 0612ce4..0000000 --- a/node_modules/hapi/examples/views/cms/views/layout.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - {{title}} - - - - - - {{> nav}} -
- {{{ content }}} -
-
-
-
- {{> footer}} -
-
- - \ No newline at end of file diff --git a/node_modules/hapi/examples/views/cms/views/page.html b/node_modules/hapi/examples/views/cms/views/page.html deleted file mode 100755 index fa42b6f..0000000 --- a/node_modules/hapi/examples/views/cms/views/page.html +++ /dev/null @@ -1,4 +0,0 @@ -

{{page.name}}

-
- {{{page.contents}}} -
\ No newline at end of file diff --git a/node_modules/hapi/examples/views/cms/views/partials/footer.html b/node_modules/hapi/examples/views/cms/views/partials/footer.html deleted file mode 100755 index 5f43518..0000000 --- a/node_modules/hapi/examples/views/cms/views/partials/footer.html +++ /dev/null @@ -1 +0,0 @@ -

© @Someone 2013

\ No newline at end of file diff --git a/node_modules/hapi/examples/views/cms/views/partials/nav.html b/node_modules/hapi/examples/views/cms/views/partials/nav.html deleted file mode 100755 index b0f1468..0000000 --- a/node_modules/hapi/examples/views/cms/views/partials/nav.html +++ /dev/null @@ -1,21 +0,0 @@ - \ No newline at end of file diff --git a/node_modules/hapi/examples/views/handlebars/basic.js b/node_modules/hapi/examples/views/handlebars/basic.js deleted file mode 100755 index a44aead..0000000 --- a/node_modules/hapi/examples/views/handlebars/basic.js +++ /dev/null @@ -1,35 +0,0 @@ -// Load modules - -var Hapi = require('../../../lib'); - - -// Declare internals - -var internals = {}; - - -var handler = function (request) { - - request.reply.view('basic/index', { - title: 'examples/views/handlebars/basic.js | Hapi ' + Hapi.utils.version(), - message: 'Hello World!' - }); -}; - - -internals.main = function () { - - var options = { - views: { - engines: { html: 'handlebars' }, - path: __dirname + '/templates' - } - }; - - var server = new Hapi.Server(8000, options); - server.route({ method: 'GET', path: '/', handler: handler }); - server.start(); -}; - - -internals.main(); diff --git a/node_modules/hapi/examples/views/handlebars/layout.js b/node_modules/hapi/examples/views/handlebars/layout.js deleted file mode 100755 index 97d165d..0000000 --- a/node_modules/hapi/examples/views/handlebars/layout.js +++ /dev/null @@ -1,37 +0,0 @@ -// Load modules - -var Hapi = require('../../../lib'); - - -// Declare internals - -var internals = {}; - - -var handler = function (request) { - - request.reply.view('withLayout/index', { - title: 'examples/views/handlebars/layout.js | Hapi ' + Hapi.utils.version(), - message: 'Hello World!\n' - }); -}; - - -internals.main = function () { - - var options = { - views: { - engines: { html: 'handlebars' }, - path: __dirname + '/templates', - layout: true - } - }; - - var server = new Hapi.Server(8000, options); - server.route({ method: 'GET', path: '/', handler: handler }); - server.start(); -}; - - -internals.main(); - diff --git a/node_modules/hapi/examples/views/handlebars/partials.js b/node_modules/hapi/examples/views/handlebars/partials.js deleted file mode 100755 index 443ab5c..0000000 --- a/node_modules/hapi/examples/views/handlebars/partials.js +++ /dev/null @@ -1,37 +0,0 @@ -// Load modules - -var Hapi = require('../../../lib'); - - -// Declare internals - -var internals = {}; - - -var handler = function (request) { - - request.reply.view('withPartials/index', { - title: 'examples/views/handlebars/partials.js | Hapi ' + Hapi.utils.version(), - message: 'Hello World!\n' - }); -}; - - -internals.main = function () { - - var options = { - views: { - engines: { html: 'handlebars' }, - path: __dirname + '/templates', - partialsPath: __dirname + '/templates/withPartials' - } - }; - - var server = new Hapi.Server(8000, options); - server.route({ method: 'GET', path: '/', handler: handler }); - server.start(); -}; - - -internals.main(); - diff --git a/node_modules/hapi/examples/views/handlebars/templates/basic/index.html b/node_modules/hapi/examples/views/handlebars/templates/basic/index.html deleted file mode 100755 index 06a1feb..0000000 --- a/node_modules/hapi/examples/views/handlebars/templates/basic/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - {{title}} - - -
-

{{message}}

-
- - diff --git a/node_modules/hapi/examples/views/handlebars/templates/layout.html b/node_modules/hapi/examples/views/handlebars/templates/layout.html deleted file mode 100755 index 21d6170..0000000 --- a/node_modules/hapi/examples/views/handlebars/templates/layout.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - {{title}} - - -

Layout header

- {{{ content }}} -

Layout footer

- - diff --git a/node_modules/hapi/examples/views/handlebars/templates/withLayout/index.html b/node_modules/hapi/examples/views/handlebars/templates/withLayout/index.html deleted file mode 100755 index 8a57a8f..0000000 --- a/node_modules/hapi/examples/views/handlebars/templates/withLayout/index.html +++ /dev/null @@ -1,3 +0,0 @@ -
-

{{message}}

-
\ No newline at end of file diff --git a/node_modules/hapi/examples/views/handlebars/templates/withPartials/footer.html b/node_modules/hapi/examples/views/handlebars/templates/withPartials/footer.html deleted file mode 100755 index 102617d..0000000 --- a/node_modules/hapi/examples/views/handlebars/templates/withPartials/footer.html +++ /dev/null @@ -1,3 +0,0 @@ -
-

hapi.js 2013

-
\ No newline at end of file diff --git a/node_modules/hapi/examples/views/handlebars/templates/withPartials/header.html b/node_modules/hapi/examples/views/handlebars/templates/withPartials/header.html deleted file mode 100755 index c23da54..0000000 --- a/node_modules/hapi/examples/views/handlebars/templates/withPartials/header.html +++ /dev/null @@ -1,3 +0,0 @@ -
-

Views with Partials

-
diff --git a/node_modules/hapi/examples/views/handlebars/templates/withPartials/index.html b/node_modules/hapi/examples/views/handlebars/templates/withPartials/index.html deleted file mode 100755 index 11d647d..0000000 --- a/node_modules/hapi/examples/views/handlebars/templates/withPartials/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - {{title}} - - - {{> header}} -
-

{{message}}

-
- {{> footer}} - - diff --git a/node_modules/hapi/examples/views/jade/index.js b/node_modules/hapi/examples/views/jade/index.js deleted file mode 100755 index ac2c152..0000000 --- a/node_modules/hapi/examples/views/jade/index.js +++ /dev/null @@ -1,47 +0,0 @@ -// Load modules - -var Hapi = require('../../../lib'); - - -// Declare internals - -var internals = {}; - - -var rootHandler = function (request) { - - request.reply.view('index', { - title: 'examples/views/jade/index.js | Hapi ' + Hapi.utils.version(), - message: 'Index - Hello World!' - }); -}; - -var aboutHandler = function (request) { - - request.reply.view('about', { - title: 'examples/views/jade/index.js | Hapi ' + Hapi.utils.version(), - message: 'About - Hello World!' - }); -}; - - -internals.main = function () { - - var options = { - views: { - engines: { jade: 'jade' }, - path: __dirname + '/templates', - compileOptions: { - pretty: true - } - } - }; - - var server = new Hapi.Server(8000, options); - server.route({ method: 'GET', path: '/', handler: rootHandler }); - server.route({ method: 'GET', path: '/about', handler: aboutHandler }); - server.start(); -}; - - -internals.main(); diff --git a/node_modules/hapi/examples/views/jade/templates/about.jade b/node_modules/hapi/examples/views/jade/templates/about.jade deleted file mode 100755 index ac539de..0000000 --- a/node_modules/hapi/examples/views/jade/templates/about.jade +++ /dev/null @@ -1,5 +0,0 @@ -extends layout - -block content - h1= title - p= message diff --git a/node_modules/hapi/examples/views/jade/templates/includes/foot.jade b/node_modules/hapi/examples/views/jade/templates/includes/foot.jade deleted file mode 100755 index 9cb2279..0000000 --- a/node_modules/hapi/examples/views/jade/templates/includes/foot.jade +++ /dev/null @@ -1,2 +0,0 @@ -#footer - p hapi.js 2013 \ No newline at end of file diff --git a/node_modules/hapi/examples/views/jade/templates/includes/head.jade b/node_modules/hapi/examples/views/jade/templates/includes/head.jade deleted file mode 100755 index defc566..0000000 --- a/node_modules/hapi/examples/views/jade/templates/includes/head.jade +++ /dev/null @@ -1,2 +0,0 @@ -head - script(src='//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js') \ No newline at end of file diff --git a/node_modules/hapi/examples/views/jade/templates/index.jade b/node_modules/hapi/examples/views/jade/templates/index.jade deleted file mode 100755 index ac539de..0000000 --- a/node_modules/hapi/examples/views/jade/templates/index.jade +++ /dev/null @@ -1,5 +0,0 @@ -extends layout - -block content - h1= title - p= message diff --git a/node_modules/hapi/examples/views/jade/templates/layout.jade b/node_modules/hapi/examples/views/jade/templates/layout.jade deleted file mode 100755 index 9d46b1c..0000000 --- a/node_modules/hapi/examples/views/jade/templates/layout.jade +++ /dev/null @@ -1,5 +0,0 @@ -html - include includes/head - body - block content - include includes/foot \ No newline at end of file diff --git a/node_modules/hapi/examples/views/mixed/index.js b/node_modules/hapi/examples/views/mixed/index.js deleted file mode 100755 index 4a2c1b7..0000000 --- a/node_modules/hapi/examples/views/mixed/index.js +++ /dev/null @@ -1,45 +0,0 @@ -// Load modules - -var Hapi = require('../../../lib'); - - -// Declare internals - -var internals = {}; - -var ctx = { - title: 'examples/views/mixed/basic.js | Hapi ' + Hapi.utils.version(), - message: 'Hello World!' -} - -var oneHandler = function (request) { - - request.reply.view('index', ctx); -}; - -var twoHandler = function (request) { - - request.reply.view('handlebars', ctx); -}; - - -internals.main = function () { - - var options = { - views: { - engines: { - 'html': 'handlebars', - 'jade': 'jade' - }, - path: __dirname + '/templates', - } - }; - - var server = new Hapi.Server(8000, options); - server.route({ method: 'GET', path: '/one', handler: oneHandler }); - server.route({ method: 'GET', path: '/two', handler: twoHandler }); - server.start(); -}; - - -internals.main(); diff --git a/node_modules/hapi/examples/views/mixed/templates/handlebars.html b/node_modules/hapi/examples/views/mixed/templates/handlebars.html deleted file mode 100755 index 49719fc..0000000 --- a/node_modules/hapi/examples/views/mixed/templates/handlebars.html +++ /dev/null @@ -1,6 +0,0 @@ - - -

I am rendered with handlebars!

- Jade Version - - \ No newline at end of file diff --git a/node_modules/hapi/examples/views/mixed/templates/index.jade b/node_modules/hapi/examples/views/mixed/templates/index.jade deleted file mode 100755 index dcd1c43..0000000 --- a/node_modules/hapi/examples/views/mixed/templates/index.jade +++ /dev/null @@ -1,4 +0,0 @@ -html - body - p "I am rendered with Jade" - a(href="/two") Handlebars Version \ No newline at end of file diff --git a/node_modules/hapi/index.js b/node_modules/hapi/index.js deleted file mode 100755 index 4cc88b3..0000000 --- a/node_modules/hapi/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./lib'); \ No newline at end of file diff --git a/node_modules/hapi/lab_runner.js b/node_modules/hapi/lab_runner.js deleted file mode 100644 index f8ddb96..0000000 --- a/node_modules/hapi/lab_runner.js +++ /dev/null @@ -1,2 +0,0 @@ -require('lab/lib/execute.js').execute(); - diff --git a/node_modules/hapi/node_modules/.bin/semver b/node_modules/hapi/node_modules/.bin/semver deleted file mode 120000 index 317eb29..0000000 --- a/node_modules/hapi/node_modules/.bin/semver +++ /dev/null @@ -1 +0,0 @@ -../semver/bin/semver \ No newline at end of file diff --git a/node_modules/hapi/node_modules/async/LICENSE b/node_modules/hapi/node_modules/async/LICENSE deleted file mode 100644 index b7f9d50..0000000 --- a/node_modules/hapi/node_modules/async/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2010 Caolan McMahon - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/node_modules/hapi/node_modules/async/README.md b/node_modules/hapi/node_modules/async/README.md deleted file mode 100644 index 951f76e..0000000 --- a/node_modules/hapi/node_modules/async/README.md +++ /dev/null @@ -1,1425 +0,0 @@ -# Async.js - -Async is a utility module which provides straight-forward, powerful functions -for working with asynchronous JavaScript. Although originally designed for -use with [node.js](http://nodejs.org), it can also be used directly in the -browser. Also supports [component](https://github.com/component/component). - -Async provides around 20 functions that include the usual 'functional' -suspects (map, reduce, filter, each…) as well as some common patterns -for asynchronous control flow (parallel, series, waterfall…). All these -functions assume you follow the node.js convention of providing a single -callback as the last argument of your async function. - - -## Quick Examples - -```javascript -async.map(['file1','file2','file3'], fs.stat, function(err, results){ - // results is now an array of stats for each file -}); - -async.filter(['file1','file2','file3'], fs.exists, function(results){ - // results now equals an array of the existing files -}); - -async.parallel([ - function(){ ... }, - function(){ ... } -], callback); - -async.series([ - function(){ ... }, - function(){ ... } -]); -``` - -There are many more functions available so take a look at the docs below for a -full list. This module aims to be comprehensive, so if you feel anything is -missing please create a GitHub issue for it. - -## Common Pitfalls - -### Binding a context to an iterator - -This section is really about bind, not about async. If you are wondering how to -make async execute your iterators in a given context, or are confused as to why -a method of another library isn't working as an iterator, study this example: - -```js -// Here is a simple object with an (unnecessarily roundabout) squaring method -var AsyncSquaringLibrary = { - squareExponent: 2, - square: function(number, callback){ - var result = Math.pow(number, this.squareExponent); - setTimeout(function(){ - callback(null, result); - }, 200); - } -}; - -async.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){ - // result is [NaN, NaN, NaN] - // This fails because the `this.squareExponent` expression in the square - // function is not evaluated in the context of AsyncSquaringLibrary, and is - // therefore undefined. -}); - -async.map([1, 2, 3], AsyncSquaringLibrary.square.bind(AsyncSquaringLibrary), function(err, result){ - // result is [1, 4, 9] - // With the help of bind we can attach a context to the iterator before - // passing it to async. Now the square function will be executed in its - // 'home' AsyncSquaringLibrary context and the value of `this.squareExponent` - // will be as expected. -}); -``` - -## Download - -The source is available for download from -[GitHub](http://github.com/caolan/async). -Alternatively, you can install using Node Package Manager (npm): - - npm install async - -__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 29.6kb Uncompressed - -## In the Browser - -So far it's been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage: - -```html - - -``` - -## Documentation - -### Collections - -* [each](#each) -* [eachSeries](#eachSeries) -* [eachLimit](#eachLimit) -* [map](#map) -* [mapSeries](#mapSeries) -* [mapLimit](#mapLimit) -* [filter](#filter) -* [filterSeries](#filterSeries) -* [reject](#reject) -* [rejectSeries](#rejectSeries) -* [reduce](#reduce) -* [reduceRight](#reduceRight) -* [detect](#detect) -* [detectSeries](#detectSeries) -* [sortBy](#sortBy) -* [some](#some) -* [every](#every) -* [concat](#concat) -* [concatSeries](#concatSeries) - -### Control Flow - -* [series](#series) -* [parallel](#parallel) -* [parallelLimit](#parallellimittasks-limit-callback) -* [whilst](#whilst) -* [doWhilst](#doWhilst) -* [until](#until) -* [doUntil](#doUntil) -* [forever](#forever) -* [waterfall](#waterfall) -* [compose](#compose) -* [applyEach](#applyEach) -* [applyEachSeries](#applyEachSeries) -* [queue](#queue) -* [cargo](#cargo) -* [auto](#auto) -* [iterator](#iterator) -* [apply](#apply) -* [nextTick](#nextTick) -* [times](#times) -* [timesSeries](#timesSeries) - -### Utils - -* [memoize](#memoize) -* [unmemoize](#unmemoize) -* [log](#log) -* [dir](#dir) -* [noConflict](#noConflict) - - -## Collections - - - -### each(arr, iterator, callback) - -Applies an iterator function to each item in an array, in parallel. -The iterator is called with an item from the list and a callback for when it -has finished. If the iterator passes an error to this callback, the main -callback for the each function is immediately called with the error. - -Note, that since this function applies the iterator to each item in parallel -there is no guarantee that the iterator functions will complete in order. - -__Arguments__ - -* arr - An array to iterate over. -* iterator(item, callback) - A function to apply to each item in the array. - The iterator is passed a callback(err) which must be called once it has - completed. If no error has occured, the callback should be run without - arguments or with an explicit null argument. -* callback(err) - A callback which is called after all the iterator functions - have finished, or an error has occurred. - -__Example__ - -```js -// assuming openFiles is an array of file names and saveFile is a function -// to save the modified contents of that file: - -async.each(openFiles, saveFile, function(err){ - // if any of the saves produced an error, err would equal that error -}); -``` - ---------------------------------------- - - - -### eachSeries(arr, iterator, callback) - -The same as each only the iterator is applied to each item in the array in -series. The next iterator is only called once the current one has completed -processing. This means the iterator functions will complete in order. - - ---------------------------------------- - - - -### eachLimit(arr, limit, iterator, callback) - -The same as each only no more than "limit" iterators will be simultaneously -running at any time. - -Note that the items are not processed in batches, so there is no guarantee that - the first "limit" iterator functions will complete before any others are -started. - -__Arguments__ - -* arr - An array to iterate over. -* limit - The maximum number of iterators to run at any time. -* iterator(item, callback) - A function to apply to each item in the array. - The iterator is passed a callback(err) which must be called once it has - completed. If no error has occured, the callback should be run without - arguments or with an explicit null argument. -* callback(err) - A callback which is called after all the iterator functions - have finished, or an error has occurred. - -__Example__ - -```js -// Assume documents is an array of JSON objects and requestApi is a -// function that interacts with a rate-limited REST api. - -async.eachLimit(documents, 20, requestApi, function(err){ - // if any of the saves produced an error, err would equal that error -}); -``` - ---------------------------------------- - - -### map(arr, iterator, callback) - -Produces a new array of values by mapping each value in the given array through -the iterator function. The iterator is called with an item from the array and a -callback for when it has finished processing. The callback takes 2 arguments, -an error and the transformed item from the array. If the iterator passes an -error to this callback, the main callback for the map function is immediately -called with the error. - -Note, that since this function applies the iterator to each item in parallel -there is no guarantee that the iterator functions will complete in order, however -the results array will be in the same order as the original array. - -__Arguments__ - -* arr - An array to iterate over. -* iterator(item, callback) - A function to apply to each item in the array. - The iterator is passed a callback(err, transformed) which must be called once - it has completed with an error (which can be null) and a transformed item. -* callback(err, results) - A callback which is called after all the iterator - functions have finished, or an error has occurred. Results is an array of the - transformed items from the original array. - -__Example__ - -```js -async.map(['file1','file2','file3'], fs.stat, function(err, results){ - // results is now an array of stats for each file -}); -``` - ---------------------------------------- - - -### mapSeries(arr, iterator, callback) - -The same as map only the iterator is applied to each item in the array in -series. The next iterator is only called once the current one has completed -processing. The results array will be in the same order as the original. - - ---------------------------------------- - - -### mapLimit(arr, limit, iterator, callback) - -The same as map only no more than "limit" iterators will be simultaneously -running at any time. - -Note that the items are not processed in batches, so there is no guarantee that - the first "limit" iterator functions will complete before any others are -started. - -__Arguments__ - -* arr - An array to iterate over. -* limit - The maximum number of iterators to run at any time. -* iterator(item, callback) - A function to apply to each item in the array. - The iterator is passed a callback(err, transformed) which must be called once - it has completed with an error (which can be null) and a transformed item. -* callback(err, results) - A callback which is called after all the iterator - functions have finished, or an error has occurred. Results is an array of the - transformed items from the original array. - -__Example__ - -```js -async.mapLimit(['file1','file2','file3'], 1, fs.stat, function(err, results){ - // results is now an array of stats for each file -}); -``` - ---------------------------------------- - - -### filter(arr, iterator, callback) - -__Alias:__ select - -Returns a new array of all the values which pass an async truth test. -_The callback for each iterator call only accepts a single argument of true or -false, it does not accept an error argument first!_ This is in-line with the -way node libraries work with truth tests like fs.exists. This operation is -performed in parallel, but the results array will be in the same order as the -original. - -__Arguments__ - -* arr - An array to iterate over. -* iterator(item, callback) - A truth test to apply to each item in the array. - The iterator is passed a callback(truthValue) which must be called with a - boolean argument once it has completed. -* callback(results) - A callback which is called after all the iterator - functions have finished. - -__Example__ - -```js -async.filter(['file1','file2','file3'], fs.exists, function(results){ - // results now equals an array of the existing files -}); -``` - ---------------------------------------- - - -### filterSeries(arr, iterator, callback) - -__alias:__ selectSeries - -The same as filter only the iterator is applied to each item in the array in -series. The next iterator is only called once the current one has completed -processing. The results array will be in the same order as the original. - ---------------------------------------- - - -### reject(arr, iterator, callback) - -The opposite of filter. Removes values that pass an async truth test. - ---------------------------------------- - - -### rejectSeries(arr, iterator, callback) - -The same as reject, only the iterator is applied to each item in the array -in series. - - ---------------------------------------- - - -### reduce(arr, memo, iterator, callback) - -__aliases:__ inject, foldl - -Reduces a list of values into a single value using an async iterator to return -each successive step. Memo is the initial state of the reduction. This -function only operates in series. For performance reasons, it may make sense to -split a call to this function into a parallel map, then use the normal -Array.prototype.reduce on the results. This function is for situations where -each step in the reduction needs to be async, if you can get the data before -reducing it then it's probably a good idea to do so. - -__Arguments__ - -* arr - An array to iterate over. -* memo - The initial state of the reduction. -* iterator(memo, item, callback) - A function applied to each item in the - array to produce the next step in the reduction. The iterator is passed a - callback(err, reduction) which accepts an optional error as its first - argument, and the state of the reduction as the second. If an error is - passed to the callback, the reduction is stopped and the main callback is - immediately called with the error. -* callback(err, result) - A callback which is called after all the iterator - functions have finished. Result is the reduced value. - -__Example__ - -```js -async.reduce([1,2,3], 0, function(memo, item, callback){ - // pointless async: - process.nextTick(function(){ - callback(null, memo + item) - }); -}, function(err, result){ - // result is now equal to the last value of memo, which is 6 -}); -``` - ---------------------------------------- - - -### reduceRight(arr, memo, iterator, callback) - -__Alias:__ foldr - -Same as reduce, only operates on the items in the array in reverse order. - - ---------------------------------------- - - -### detect(arr, iterator, callback) - -Returns the first value in a list that passes an async truth test. The -iterator is applied in parallel, meaning the first iterator to return true will -fire the detect callback with that result. That means the result might not be -the first item in the original array (in terms of order) that passes the test. - -If order within the original array is important then look at detectSeries. - -__Arguments__ - -* arr - An array to iterate over. -* iterator(item, callback) - A truth test to apply to each item in the array. - The iterator is passed a callback(truthValue) which must be called with a - boolean argument once it has completed. -* callback(result) - A callback which is called as soon as any iterator returns - true, or after all the iterator functions have finished. Result will be - the first item in the array that passes the truth test (iterator) or the - value undefined if none passed. - -__Example__ - -```js -async.detect(['file1','file2','file3'], fs.exists, function(result){ - // result now equals the first file in the list that exists -}); -``` - ---------------------------------------- - - -### detectSeries(arr, iterator, callback) - -The same as detect, only the iterator is applied to each item in the array -in series. This means the result is always the first in the original array (in -terms of array order) that passes the truth test. - - ---------------------------------------- - - -### sortBy(arr, iterator, callback) - -Sorts a list by the results of running each value through an async iterator. - -__Arguments__ - -* arr - An array to iterate over. -* iterator(item, callback) - A function to apply to each item in the array. - The iterator is passed a callback(err, sortValue) which must be called once it - has completed with an error (which can be null) and a value to use as the sort - criteria. -* callback(err, results) - A callback which is called after all the iterator - functions have finished, or an error has occurred. Results is the items from - the original array sorted by the values returned by the iterator calls. - -__Example__ - -```js -async.sortBy(['file1','file2','file3'], function(file, callback){ - fs.stat(file, function(err, stats){ - callback(err, stats.mtime); - }); -}, function(err, results){ - // results is now the original array of files sorted by - // modified date -}); -``` - ---------------------------------------- - - -### some(arr, iterator, callback) - -__Alias:__ any - -Returns true if at least one element in the array satisfies an async test. -_The callback for each iterator call only accepts a single argument of true or -false, it does not accept an error argument first!_ This is in-line with the -way node libraries work with truth tests like fs.exists. Once any iterator -call returns true, the main callback is immediately called. - -__Arguments__ - -* arr - An array to iterate over. -* iterator(item, callback) - A truth test to apply to each item in the array. - The iterator is passed a callback(truthValue) which must be called with a - boolean argument once it has completed. -* callback(result) - A callback which is called as soon as any iterator returns - true, or after all the iterator functions have finished. Result will be - either true or false depending on the values of the async tests. - -__Example__ - -```js -async.some(['file1','file2','file3'], fs.exists, function(result){ - // if result is true then at least one of the files exists -}); -``` - ---------------------------------------- - - -### every(arr, iterator, callback) - -__Alias:__ all - -Returns true if every element in the array satisfies an async test. -_The callback for each iterator call only accepts a single argument of true or -false, it does not accept an error argument first!_ This is in-line with the -way node libraries work with truth tests like fs.exists. - -__Arguments__ - -* arr - An array to iterate over. -* iterator(item, callback) - A truth test to apply to each item in the array. - The iterator is passed a callback(truthValue) which must be called with a - boolean argument once it has completed. -* callback(result) - A callback which is called after all the iterator - functions have finished. Result will be either true or false depending on - the values of the async tests. - -__Example__ - -```js -async.every(['file1','file2','file3'], fs.exists, function(result){ - // if result is true then every file exists -}); -``` - ---------------------------------------- - - -### concat(arr, iterator, callback) - -Applies an iterator to each item in a list, concatenating the results. Returns the -concatenated list. The iterators are called in parallel, and the results are -concatenated as they return. There is no guarantee that the results array will -be returned in the original order of the arguments passed to the iterator function. - -__Arguments__ - -* arr - An array to iterate over -* iterator(item, callback) - A function to apply to each item in the array. - The iterator is passed a callback(err, results) which must be called once it - has completed with an error (which can be null) and an array of results. -* callback(err, results) - A callback which is called after all the iterator - functions have finished, or an error has occurred. Results is an array containing - the concatenated results of the iterator function. - -__Example__ - -```js -async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ - // files is now a list of filenames that exist in the 3 directories -}); -``` - ---------------------------------------- - - -### concatSeries(arr, iterator, callback) - -Same as async.concat, but executes in series instead of parallel. - - -## Control Flow - - -### series(tasks, [callback]) - -Run an array of functions in series, each one running once the previous -function has completed. If any functions in the series pass an error to its -callback, no more functions are run and the callback for the series is -immediately called with the value of the error. Once the tasks have completed, -the results are passed to the final callback as an array. - -It is also possible to use an object instead of an array. Each property will be -run as a function and the results will be passed to the final callback as an object -instead of an array. This can be a more readable way of handling results from -async.series. - - -__Arguments__ - -* tasks - An array or object containing functions to run, each function is passed - a callback(err, result) it must call on completion with an error (which can - be null) and an optional result value. -* callback(err, results) - An optional callback to run once all the functions - have completed. This function gets a results array (or object) containing all - the result arguments passed to the task callbacks. - -__Example__ - -```js -async.series([ - function(callback){ - // do some stuff ... - callback(null, 'one'); - }, - function(callback){ - // do some more stuff ... - callback(null, 'two'); - } -], -// optional callback -function(err, results){ - // results is now equal to ['one', 'two'] -}); - - -// an example using an object instead of an array -async.series({ - one: function(callback){ - setTimeout(function(){ - callback(null, 1); - }, 200); - }, - two: function(callback){ - setTimeout(function(){ - callback(null, 2); - }, 100); - } -}, -function(err, results) { - // results is now equal to: {one: 1, two: 2} -}); -``` - ---------------------------------------- - - -### parallel(tasks, [callback]) - -Run an array of functions in parallel, without waiting until the previous -function has completed. If any of the functions pass an error to its -callback, the main callback is immediately called with the value of the error. -Once the tasks have completed, the results are passed to the final callback as an -array. - -It is also possible to use an object instead of an array. Each property will be -run as a function and the results will be passed to the final callback as an object -instead of an array. This can be a more readable way of handling results from -async.parallel. - - -__Arguments__ - -* tasks - An array or object containing functions to run, each function is passed - a callback(err, result) it must call on completion with an error (which can - be null) and an optional result value. -* callback(err, results) - An optional callback to run once all the functions - have completed. This function gets a results array (or object) containing all - the result arguments passed to the task callbacks. - -__Example__ - -```js -async.parallel([ - function(callback){ - setTimeout(function(){ - callback(null, 'one'); - }, 200); - }, - function(callback){ - setTimeout(function(){ - callback(null, 'two'); - }, 100); - } -], -// optional callback -function(err, results){ - // the results array will equal ['one','two'] even though - // the second function had a shorter timeout. -}); - - -// an example using an object instead of an array -async.parallel({ - one: function(callback){ - setTimeout(function(){ - callback(null, 1); - }, 200); - }, - two: function(callback){ - setTimeout(function(){ - callback(null, 2); - }, 100); - } -}, -function(err, results) { - // results is now equals to: {one: 1, two: 2} -}); -``` - ---------------------------------------- - - -### parallelLimit(tasks, limit, [callback]) - -The same as parallel only the tasks are executed in parallel with a maximum of "limit" -tasks executing at any time. - -Note that the tasks are not executed in batches, so there is no guarantee that -the first "limit" tasks will complete before any others are started. - -__Arguments__ - -* tasks - An array or object containing functions to run, each function is passed - a callback(err, result) it must call on completion with an error (which can - be null) and an optional result value. -* limit - The maximum number of tasks to run at any time. -* callback(err, results) - An optional callback to run once all the functions - have completed. This function gets a results array (or object) containing all - the result arguments passed to the task callbacks. - ---------------------------------------- - - -### whilst(test, fn, callback) - -Repeatedly call fn, while test returns true. Calls the callback when stopped, -or an error occurs. - -__Arguments__ - -* test() - synchronous truth test to perform before each execution of fn. -* fn(callback) - A function to call each time the test passes. The function is - passed a callback(err) which must be called once it has completed with an - optional error argument. -* callback(err) - A callback which is called after the test fails and repeated - execution of fn has stopped. - -__Example__ - -```js -var count = 0; - -async.whilst( - function () { return count < 5; }, - function (callback) { - count++; - setTimeout(callback, 1000); - }, - function (err) { - // 5 seconds have passed - } -); -``` - ---------------------------------------- - - -### doWhilst(fn, test, callback) - -The post check version of whilst. To reflect the difference in the order of operations `test` and `fn` arguments are switched. `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript. - ---------------------------------------- - - -### until(test, fn, callback) - -Repeatedly call fn, until test returns true. Calls the callback when stopped, -or an error occurs. - -The inverse of async.whilst. - ---------------------------------------- - - -### doUntil(fn, test, callback) - -Like doWhilst except the test is inverted. Note the argument ordering differs from `until`. - ---------------------------------------- - - -### forever(fn, callback) - -Calls the asynchronous function 'fn' repeatedly, in series, indefinitely. -If an error is passed to fn's callback then 'callback' is called with the -error, otherwise it will never be called. - ---------------------------------------- - - -### waterfall(tasks, [callback]) - -Runs an array of functions in series, each passing their results to the next in -the array. However, if any of the functions pass an error to the callback, the -next function is not executed and the main callback is immediately called with -the error. - -__Arguments__ - -* tasks - An array of functions to run, each function is passed a - callback(err, result1, result2, ...) it must call on completion. The first - argument is an error (which can be null) and any further arguments will be - passed as arguments in order to the next task. -* callback(err, [results]) - An optional callback to run once all the functions - have completed. This will be passed the results of the last task's callback. - - - -__Example__ - -```js -async.waterfall([ - function(callback){ - callback(null, 'one', 'two'); - }, - function(arg1, arg2, callback){ - callback(null, 'three'); - }, - function(arg1, callback){ - // arg1 now equals 'three' - callback(null, 'done'); - } -], function (err, result) { - // result now equals 'done' -}); -``` - ---------------------------------------- - -### compose(fn1, fn2...) - -Creates a function which is a composition of the passed asynchronous -functions. Each function consumes the return value of the function that -follows. Composing functions f(), g() and h() would produce the result of -f(g(h())), only this version uses callbacks to obtain the return values. - -Each function is executed with the `this` binding of the composed function. - -__Arguments__ - -* functions... - the asynchronous functions to compose - - -__Example__ - -```js -function add1(n, callback) { - setTimeout(function () { - callback(null, n + 1); - }, 10); -} - -function mul3(n, callback) { - setTimeout(function () { - callback(null, n * 3); - }, 10); -} - -var add1mul3 = async.compose(mul3, add1); - -add1mul3(4, function (err, result) { - // result now equals 15 -}); -``` - ---------------------------------------- - -### applyEach(fns, args..., callback) - -Applies the provided arguments to each function in the array, calling the -callback after all functions have completed. If you only provide the first -argument then it will return a function which lets you pass in the -arguments as if it were a single function call. - -__Arguments__ - -* fns - the asynchronous functions to all call with the same arguments -* args... - any number of separate arguments to pass to the function -* callback - the final argument should be the callback, called when all - functions have completed processing - - -__Example__ - -```js -async.applyEach([enableSearch, updateSchema], 'bucket', callback); - -// partial application example: -async.each( - buckets, - async.applyEach([enableSearch, updateSchema]), - callback -); -``` - ---------------------------------------- - - -### applyEachSeries(arr, iterator, callback) - -The same as applyEach only the functions are applied in series. - ---------------------------------------- - - -### queue(worker, concurrency) - -Creates a queue object with the specified concurrency. Tasks added to the -queue will be processed in parallel (up to the concurrency limit). If all -workers are in progress, the task is queued until one is available. Once -a worker has completed a task, the task's callback is called. - -__Arguments__ - -* worker(task, callback) - An asynchronous function for processing a queued - task, which must call its callback(err) argument when finished, with an - optional error as an argument. -* concurrency - An integer for determining how many worker functions should be - run in parallel. - -__Queue objects__ - -The queue object returned by this function has the following properties and -methods: - -* length() - a function returning the number of items waiting to be processed. -* concurrency - an integer for determining how many worker functions should be - run in parallel. This property can be changed after a queue is created to - alter the concurrency on-the-fly. -* push(task, [callback]) - add a new task to the queue, the callback is called - once the worker has finished processing the task. - instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list. -* unshift(task, [callback]) - add a new task to the front of the queue. -* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued -* empty - a callback that is called when the last item from the queue is given to a worker -* drain - a callback that is called when the last item from the queue has returned from the worker - -__Example__ - -```js -// create a queue object with concurrency 2 - -var q = async.queue(function (task, callback) { - console.log('hello ' + task.name); - callback(); -}, 2); - - -// assign a callback -q.drain = function() { - console.log('all items have been processed'); -} - -// add some items to the queue - -q.push({name: 'foo'}, function (err) { - console.log('finished processing foo'); -}); -q.push({name: 'bar'}, function (err) { - console.log('finished processing bar'); -}); - -// add some items to the queue (batch-wise) - -q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) { - console.log('finished processing bar'); -}); - -// add some items to the front of the queue - -q.unshift({name: 'bar'}, function (err) { - console.log('finished processing bar'); -}); -``` - ---------------------------------------- - - -### cargo(worker, [payload]) - -Creates a cargo object with the specified payload. Tasks added to the -cargo will be processed altogether (up to the payload limit). If the -worker is in progress, the task is queued until it is available. Once -the worker has completed some tasks, each callback of those tasks is called. - -__Arguments__ - -* worker(tasks, callback) - An asynchronous function for processing an array of - queued tasks, which must call its callback(err) argument when finished, with - an optional error as an argument. -* payload - An optional integer for determining how many tasks should be - processed per round; if omitted, the default is unlimited. - -__Cargo objects__ - -The cargo object returned by this function has the following properties and -methods: - -* length() - a function returning the number of items waiting to be processed. -* payload - an integer for determining how many tasks should be - process per round. This property can be changed after a cargo is created to - alter the payload on-the-fly. -* push(task, [callback]) - add a new task to the queue, the callback is called - once the worker has finished processing the task. - instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list. -* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued -* empty - a callback that is called when the last item from the queue is given to a worker -* drain - a callback that is called when the last item from the queue has returned from the worker - -__Example__ - -```js -// create a cargo object with payload 2 - -var cargo = async.cargo(function (tasks, callback) { - for(var i=0; i -### auto(tasks, [callback]) - -Determines the best order for running functions based on their requirements. -Each function can optionally depend on other functions being completed first, -and each function is run as soon as its requirements are satisfied. If any of -the functions pass an error to their callback, that function will not complete -(so any other functions depending on it will not run) and the main callback -will be called immediately with the error. Functions also receive an object -containing the results of functions which have completed so far. - -Note, all functions are called with a results object as a second argument, -so it is unsafe to pass functions in the tasks object which cannot handle the -extra argument. For example, this snippet of code: - -```js -async.auto({ - readData: async.apply(fs.readFile, 'data.txt', 'utf-8') -}, callback); -``` - -will have the effect of calling readFile with the results object as the last -argument, which will fail: - -```js -fs.readFile('data.txt', 'utf-8', cb, {}); -``` - -Instead, wrap the call to readFile in a function which does not forward the -results object: - -```js -async.auto({ - readData: function(cb, results){ - fs.readFile('data.txt', 'utf-8', cb); - } -}, callback); -``` - -__Arguments__ - -* tasks - An object literal containing named functions or an array of - requirements, with the function itself the last item in the array. The key - used for each function or array is used when specifying requirements. The - function receives two arguments: (1) a callback(err, result) which must be - called when finished, passing an error (which can be null) and the result of - the function's execution, and (2) a results object, containing the results of - the previously executed functions. -* callback(err, results) - An optional callback which is called when all the - tasks have been completed. The callback will receive an error as an argument - if any tasks pass an error to their callback. Results will always be passed - but if an error occurred, no other tasks will be performed, and the results - object will only contain partial results. - - -__Example__ - -```js -async.auto({ - get_data: function(callback){ - // async code to get some data - }, - make_folder: function(callback){ - // async code to create a directory to store a file in - // this is run at the same time as getting the data - }, - write_file: ['get_data', 'make_folder', function(callback){ - // once there is some data and the directory exists, - // write the data to a file in the directory - callback(null, filename); - }], - email_link: ['write_file', function(callback, results){ - // once the file is written let's email a link to it... - // results.write_file contains the filename returned by write_file. - }] -}); -``` - -This is a fairly trivial example, but to do this using the basic parallel and -series functions would look like this: - -```js -async.parallel([ - function(callback){ - // async code to get some data - }, - function(callback){ - // async code to create a directory to store a file in - // this is run at the same time as getting the data - } -], -function(err, results){ - async.series([ - function(callback){ - // once there is some data and the directory exists, - // write the data to a file in the directory - }, - function(callback){ - // once the file is written let's email a link to it... - } - ]); -}); -``` - -For a complicated series of async tasks using the auto function makes adding -new tasks much easier and makes the code more readable. - - ---------------------------------------- - - -### iterator(tasks) - -Creates an iterator function which calls the next function in the array, -returning a continuation to call the next one after that. It's also possible to -'peek' the next iterator by doing iterator.next(). - -This function is used internally by the async module but can be useful when -you want to manually control the flow of functions in series. - -__Arguments__ - -* tasks - An array of functions to run. - -__Example__ - -```js -var iterator = async.iterator([ - function(){ sys.p('one'); }, - function(){ sys.p('two'); }, - function(){ sys.p('three'); } -]); - -node> var iterator2 = iterator(); -'one' -node> var iterator3 = iterator2(); -'two' -node> iterator3(); -'three' -node> var nextfn = iterator2.next(); -node> nextfn(); -'three' -``` - ---------------------------------------- - - -### apply(function, arguments..) - -Creates a continuation function with some arguments already applied, a useful -shorthand when combined with other control flow functions. Any arguments -passed to the returned function are added to the arguments originally passed -to apply. - -__Arguments__ - -* function - The function you want to eventually apply all arguments to. -* arguments... - Any number of arguments to automatically apply when the - continuation is called. - -__Example__ - -```js -// using apply - -async.parallel([ - async.apply(fs.writeFile, 'testfile1', 'test1'), - async.apply(fs.writeFile, 'testfile2', 'test2'), -]); - - -// the same process without using apply - -async.parallel([ - function(callback){ - fs.writeFile('testfile1', 'test1', callback); - }, - function(callback){ - fs.writeFile('testfile2', 'test2', callback); - } -]); -``` - -It's possible to pass any number of additional arguments when calling the -continuation: - -```js -node> var fn = async.apply(sys.puts, 'one'); -node> fn('two', 'three'); -one -two -three -``` - ---------------------------------------- - - -### nextTick(callback) - -Calls the callback on a later loop around the event loop. In node.js this just -calls process.nextTick, in the browser it falls back to setImmediate(callback) -if available, otherwise setTimeout(callback, 0), which means other higher priority -events may precede the execution of the callback. - -This is used internally for browser-compatibility purposes. - -__Arguments__ - -* callback - The function to call on a later loop around the event loop. - -__Example__ - -```js -var call_order = []; -async.nextTick(function(){ - call_order.push('two'); - // call_order now equals ['one','two'] -}); -call_order.push('one') -``` - - -### times(n, callback) - -Calls the callback n times and accumulates results in the same manner -you would use with async.map. - -__Arguments__ - -* n - The number of times to run the function. -* callback - The function to call n times. - -__Example__ - -```js -// Pretend this is some complicated async factory -var createUser = function(id, callback) { - callback(null, { - id: 'user' + id - }) -} -// generate 5 users -async.times(5, function(n, next){ - createUser(n, function(err, user) { - next(err, user) - }) -}, function(err, users) { - // we should now have 5 users -}); -``` - - -### timesSeries(n, callback) - -The same as times only the iterator is applied to each item in the array in -series. The next iterator is only called once the current one has completed -processing. The results array will be in the same order as the original. - - -## Utils - - -### memoize(fn, [hasher]) - -Caches the results of an async function. When creating a hash to store function -results against, the callback is omitted from the hash and an optional hash -function can be used. - -The cache of results is exposed as the `memo` property of the function returned -by `memoize`. - -__Arguments__ - -* fn - the function you to proxy and cache results from. -* hasher - an optional function for generating a custom hash for storing - results, it has all the arguments applied to it apart from the callback, and - must be synchronous. - -__Example__ - -```js -var slow_fn = function (name, callback) { - // do something - callback(null, result); -}; -var fn = async.memoize(slow_fn); - -// fn can now be used as if it were slow_fn -fn('some name', function () { - // callback -}); -``` - - -### unmemoize(fn) - -Undoes a memoized function, reverting it to the original, unmemoized -form. Comes handy in tests. - -__Arguments__ - -* fn - the memoized function - - -### log(function, arguments) - -Logs the result of an async function to the console. Only works in node.js or -in browsers that support console.log and console.error (such as FF and Chrome). -If multiple arguments are returned from the async function, console.log is -called on each argument in order. - -__Arguments__ - -* function - The function you want to eventually apply all arguments to. -* arguments... - Any number of arguments to apply to the function. - -__Example__ - -```js -var hello = function(name, callback){ - setTimeout(function(){ - callback(null, 'hello ' + name); - }, 1000); -}; -``` -```js -node> async.log(hello, 'world'); -'hello world' -``` - ---------------------------------------- - - -### dir(function, arguments) - -Logs the result of an async function to the console using console.dir to -display the properties of the resulting object. Only works in node.js or -in browsers that support console.dir and console.error (such as FF and Chrome). -If multiple arguments are returned from the async function, console.dir is -called on each argument in order. - -__Arguments__ - -* function - The function you want to eventually apply all arguments to. -* arguments... - Any number of arguments to apply to the function. - -__Example__ - -```js -var hello = function(name, callback){ - setTimeout(function(){ - callback(null, {hello: name}); - }, 1000); -}; -``` -```js -node> async.dir(hello, 'world'); -{hello: 'world'} -``` - ---------------------------------------- - - -### noConflict() - -Changes the value of async back to its original value, returning a reference to the -async object. diff --git a/node_modules/hapi/node_modules/async/component.json b/node_modules/hapi/node_modules/async/component.json deleted file mode 100644 index bbb0115..0000000 --- a/node_modules/hapi/node_modules/async/component.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "async", - "repo": "caolan/async", - "description": "Higher-order functions and common patterns for asynchronous code", - "version": "0.1.23", - "keywords": [], - "dependencies": {}, - "development": {}, - "main": "lib/async.js", - "scripts": [ "lib/async.js" ] -} diff --git a/node_modules/hapi/node_modules/async/package.json b/node_modules/hapi/node_modules/async/package.json deleted file mode 100644 index f57ffec..0000000 --- a/node_modules/hapi/node_modules/async/package.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "name": "async", - "description": "Higher-order functions and common patterns for asynchronous code", - "main": "./lib/async", - "author": { - "name": "Caolan McMahon" - }, - "version": "0.2.10", - "repository": { - "type": "git", - "url": "git+https://github.com/caolan/async.git" - }, - "bugs": { - "url": "https://github.com/caolan/async/issues" - }, - "licenses": [ - { - "type": "MIT", - "url": "https://github.com/caolan/async/raw/master/LICENSE" - } - ], - "devDependencies": { - "nodeunit": ">0.0.0", - "uglify-js": "1.2.x", - "nodelint": ">0.0.0" - }, - "jam": { - "main": "lib/async.js", - "include": [ - "lib/async.js", - "README.md", - "LICENSE" - ] - }, - "scripts": { - "test": "nodeunit test/test-async.js" - }, - "_id": "async@0.2.10", - "dist": { - "shasum": "b6bbe0b0674b9d719708ca38de8c237cb526c3d1", - "tarball": "http://registry.npmjs.org/async/-/async-0.2.10.tgz" - }, - "_from": "async@>=0.2.0 <0.3.0", - "_npmVersion": "1.3.2", - "_npmUser": { - "name": "caolan", - "email": "caolan.mcmahon@gmail.com" - }, - "maintainers": [ - { - "name": "caolan", - "email": "caolan@caolanmcmahon.com" - } - ], - "directories": {}, - "_shasum": "b6bbe0b0674b9d719708ca38de8c237cb526c3d1", - "_resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "readme": "# Async.js\n\nAsync is a utility module which provides straight-forward, powerful functions\nfor working with asynchronous JavaScript. Although originally designed for\nuse with [node.js](http://nodejs.org), it can also be used directly in the\nbrowser. Also supports [component](https://github.com/component/component).\n\nAsync provides around 20 functions that include the usual 'functional'\nsuspects (map, reduce, filter, each…) as well as some common patterns\nfor asynchronous control flow (parallel, series, waterfall…). All these\nfunctions assume you follow the node.js convention of providing a single\ncallback as the last argument of your async function.\n\n\n## Quick Examples\n\n```javascript\nasync.map(['file1','file2','file3'], fs.stat, function(err, results){\n // results is now an array of stats for each file\n});\n\nasync.filter(['file1','file2','file3'], fs.exists, function(results){\n // results now equals an array of the existing files\n});\n\nasync.parallel([\n function(){ ... },\n function(){ ... }\n], callback);\n\nasync.series([\n function(){ ... },\n function(){ ... }\n]);\n```\n\nThere are many more functions available so take a look at the docs below for a\nfull list. This module aims to be comprehensive, so if you feel anything is\nmissing please create a GitHub issue for it.\n\n## Common Pitfalls\n\n### Binding a context to an iterator\n\nThis section is really about bind, not about async. If you are wondering how to\nmake async execute your iterators in a given context, or are confused as to why\na method of another library isn't working as an iterator, study this example:\n\n```js\n// Here is a simple object with an (unnecessarily roundabout) squaring method\nvar AsyncSquaringLibrary = {\n squareExponent: 2,\n square: function(number, callback){ \n var result = Math.pow(number, this.squareExponent);\n setTimeout(function(){\n callback(null, result);\n }, 200);\n }\n};\n\nasync.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){\n // result is [NaN, NaN, NaN]\n // This fails because the `this.squareExponent` expression in the square\n // function is not evaluated in the context of AsyncSquaringLibrary, and is\n // therefore undefined.\n});\n\nasync.map([1, 2, 3], AsyncSquaringLibrary.square.bind(AsyncSquaringLibrary), function(err, result){\n // result is [1, 4, 9]\n // With the help of bind we can attach a context to the iterator before\n // passing it to async. Now the square function will be executed in its \n // 'home' AsyncSquaringLibrary context and the value of `this.squareExponent`\n // will be as expected.\n});\n```\n\n## Download\n\nThe source is available for download from\n[GitHub](http://github.com/caolan/async).\nAlternatively, you can install using Node Package Manager (npm):\n\n npm install async\n\n__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 29.6kb Uncompressed\n\n## In the Browser\n\nSo far it's been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage:\n\n```html\n\n\n```\n\n## Documentation\n\n### Collections\n\n* [each](#each)\n* [eachSeries](#eachSeries)\n* [eachLimit](#eachLimit)\n* [map](#map)\n* [mapSeries](#mapSeries)\n* [mapLimit](#mapLimit)\n* [filter](#filter)\n* [filterSeries](#filterSeries)\n* [reject](#reject)\n* [rejectSeries](#rejectSeries)\n* [reduce](#reduce)\n* [reduceRight](#reduceRight)\n* [detect](#detect)\n* [detectSeries](#detectSeries)\n* [sortBy](#sortBy)\n* [some](#some)\n* [every](#every)\n* [concat](#concat)\n* [concatSeries](#concatSeries)\n\n### Control Flow\n\n* [series](#series)\n* [parallel](#parallel)\n* [parallelLimit](#parallellimittasks-limit-callback)\n* [whilst](#whilst)\n* [doWhilst](#doWhilst)\n* [until](#until)\n* [doUntil](#doUntil)\n* [forever](#forever)\n* [waterfall](#waterfall)\n* [compose](#compose)\n* [applyEach](#applyEach)\n* [applyEachSeries](#applyEachSeries)\n* [queue](#queue)\n* [cargo](#cargo)\n* [auto](#auto)\n* [iterator](#iterator)\n* [apply](#apply)\n* [nextTick](#nextTick)\n* [times](#times)\n* [timesSeries](#timesSeries)\n\n### Utils\n\n* [memoize](#memoize)\n* [unmemoize](#unmemoize)\n* [log](#log)\n* [dir](#dir)\n* [noConflict](#noConflict)\n\n\n## Collections\n\n\n\n### each(arr, iterator, callback)\n\nApplies an iterator function to each item in an array, in parallel.\nThe iterator is called with an item from the list and a callback for when it\nhas finished. If the iterator passes an error to this callback, the main\ncallback for the each function is immediately called with the error.\n\nNote, that since this function applies the iterator to each item in parallel\nthere is no guarantee that the iterator functions will complete in order.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err) which must be called once it has \n completed. If no error has occured, the callback should be run without \n arguments or with an explicit null argument.\n* callback(err) - A callback which is called after all the iterator functions\n have finished, or an error has occurred.\n\n__Example__\n\n```js\n// assuming openFiles is an array of file names and saveFile is a function\n// to save the modified contents of that file:\n\nasync.each(openFiles, saveFile, function(err){\n // if any of the saves produced an error, err would equal that error\n});\n```\n\n---------------------------------------\n\n\n\n### eachSeries(arr, iterator, callback)\n\nThe same as each only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. This means the iterator functions will complete in order.\n\n\n---------------------------------------\n\n\n\n### eachLimit(arr, limit, iterator, callback)\n\nThe same as each only no more than \"limit\" iterators will be simultaneously \nrunning at any time.\n\nNote that the items are not processed in batches, so there is no guarantee that\n the first \"limit\" iterator functions will complete before any others are \nstarted.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* limit - The maximum number of iterators to run at any time.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err) which must be called once it has \n completed. If no error has occured, the callback should be run without \n arguments or with an explicit null argument.\n* callback(err) - A callback which is called after all the iterator functions\n have finished, or an error has occurred.\n\n__Example__\n\n```js\n// Assume documents is an array of JSON objects and requestApi is a\n// function that interacts with a rate-limited REST api.\n\nasync.eachLimit(documents, 20, requestApi, function(err){\n // if any of the saves produced an error, err would equal that error\n});\n```\n\n---------------------------------------\n\n\n### map(arr, iterator, callback)\n\nProduces a new array of values by mapping each value in the given array through\nthe iterator function. The iterator is called with an item from the array and a\ncallback for when it has finished processing. The callback takes 2 arguments, \nan error and the transformed item from the array. If the iterator passes an\nerror to this callback, the main callback for the map function is immediately\ncalled with the error.\n\nNote, that since this function applies the iterator to each item in parallel\nthere is no guarantee that the iterator functions will complete in order, however\nthe results array will be in the same order as the original array.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, transformed) which must be called once \n it has completed with an error (which can be null) and a transformed item.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array of the\n transformed items from the original array.\n\n__Example__\n\n```js\nasync.map(['file1','file2','file3'], fs.stat, function(err, results){\n // results is now an array of stats for each file\n});\n```\n\n---------------------------------------\n\n\n### mapSeries(arr, iterator, callback)\n\nThe same as map only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n\n---------------------------------------\n\n\n### mapLimit(arr, limit, iterator, callback)\n\nThe same as map only no more than \"limit\" iterators will be simultaneously \nrunning at any time.\n\nNote that the items are not processed in batches, so there is no guarantee that\n the first \"limit\" iterator functions will complete before any others are \nstarted.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* limit - The maximum number of iterators to run at any time.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, transformed) which must be called once \n it has completed with an error (which can be null) and a transformed item.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array of the\n transformed items from the original array.\n\n__Example__\n\n```js\nasync.mapLimit(['file1','file2','file3'], 1, fs.stat, function(err, results){\n // results is now an array of stats for each file\n});\n```\n\n---------------------------------------\n\n\n### filter(arr, iterator, callback)\n\n__Alias:__ select\n\nReturns a new array of all the values which pass an async truth test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like fs.exists. This operation is\nperformed in parallel, but the results array will be in the same order as the\noriginal.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(results) - A callback which is called after all the iterator\n functions have finished.\n\n__Example__\n\n```js\nasync.filter(['file1','file2','file3'], fs.exists, function(results){\n // results now equals an array of the existing files\n});\n```\n\n---------------------------------------\n\n\n### filterSeries(arr, iterator, callback)\n\n__alias:__ selectSeries\n\nThe same as filter only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n---------------------------------------\n\n\n### reject(arr, iterator, callback)\n\nThe opposite of filter. Removes values that pass an async truth test.\n\n---------------------------------------\n\n\n### rejectSeries(arr, iterator, callback)\n\nThe same as reject, only the iterator is applied to each item in the array\nin series.\n\n\n---------------------------------------\n\n\n### reduce(arr, memo, iterator, callback)\n\n__aliases:__ inject, foldl\n\nReduces a list of values into a single value using an async iterator to return\neach successive step. Memo is the initial state of the reduction. This\nfunction only operates in series. For performance reasons, it may make sense to\nsplit a call to this function into a parallel map, then use the normal\nArray.prototype.reduce on the results. This function is for situations where\neach step in the reduction needs to be async, if you can get the data before\nreducing it then it's probably a good idea to do so.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* memo - The initial state of the reduction.\n* iterator(memo, item, callback) - A function applied to each item in the\n array to produce the next step in the reduction. The iterator is passed a\n callback(err, reduction) which accepts an optional error as its first \n argument, and the state of the reduction as the second. If an error is \n passed to the callback, the reduction is stopped and the main callback is \n immediately called with the error.\n* callback(err, result) - A callback which is called after all the iterator\n functions have finished. Result is the reduced value.\n\n__Example__\n\n```js\nasync.reduce([1,2,3], 0, function(memo, item, callback){\n // pointless async:\n process.nextTick(function(){\n callback(null, memo + item)\n });\n}, function(err, result){\n // result is now equal to the last value of memo, which is 6\n});\n```\n\n---------------------------------------\n\n\n### reduceRight(arr, memo, iterator, callback)\n\n__Alias:__ foldr\n\nSame as reduce, only operates on the items in the array in reverse order.\n\n\n---------------------------------------\n\n\n### detect(arr, iterator, callback)\n\nReturns the first value in a list that passes an async truth test. The\niterator is applied in parallel, meaning the first iterator to return true will\nfire the detect callback with that result. That means the result might not be\nthe first item in the original array (in terms of order) that passes the test.\n\nIf order within the original array is important then look at detectSeries.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(result) - A callback which is called as soon as any iterator returns\n true, or after all the iterator functions have finished. Result will be\n the first item in the array that passes the truth test (iterator) or the\n value undefined if none passed.\n\n__Example__\n\n```js\nasync.detect(['file1','file2','file3'], fs.exists, function(result){\n // result now equals the first file in the list that exists\n});\n```\n\n---------------------------------------\n\n\n### detectSeries(arr, iterator, callback)\n\nThe same as detect, only the iterator is applied to each item in the array\nin series. This means the result is always the first in the original array (in\nterms of array order) that passes the truth test.\n\n\n---------------------------------------\n\n\n### sortBy(arr, iterator, callback)\n\nSorts a list by the results of running each value through an async iterator.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, sortValue) which must be called once it\n has completed with an error (which can be null) and a value to use as the sort\n criteria.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is the items from\n the original array sorted by the values returned by the iterator calls.\n\n__Example__\n\n```js\nasync.sortBy(['file1','file2','file3'], function(file, callback){\n fs.stat(file, function(err, stats){\n callback(err, stats.mtime);\n });\n}, function(err, results){\n // results is now the original array of files sorted by\n // modified date\n});\n```\n\n---------------------------------------\n\n\n### some(arr, iterator, callback)\n\n__Alias:__ any\n\nReturns true if at least one element in the array satisfies an async test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like fs.exists. Once any iterator\ncall returns true, the main callback is immediately called.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(result) - A callback which is called as soon as any iterator returns\n true, or after all the iterator functions have finished. Result will be\n either true or false depending on the values of the async tests.\n\n__Example__\n\n```js\nasync.some(['file1','file2','file3'], fs.exists, function(result){\n // if result is true then at least one of the files exists\n});\n```\n\n---------------------------------------\n\n\n### every(arr, iterator, callback)\n\n__Alias:__ all\n\nReturns true if every element in the array satisfies an async test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like fs.exists.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(result) - A callback which is called after all the iterator\n functions have finished. Result will be either true or false depending on\n the values of the async tests.\n\n__Example__\n\n```js\nasync.every(['file1','file2','file3'], fs.exists, function(result){\n // if result is true then every file exists\n});\n```\n\n---------------------------------------\n\n\n### concat(arr, iterator, callback)\n\nApplies an iterator to each item in a list, concatenating the results. Returns the\nconcatenated list. The iterators are called in parallel, and the results are\nconcatenated as they return. There is no guarantee that the results array will\nbe returned in the original order of the arguments passed to the iterator function.\n\n__Arguments__\n\n* arr - An array to iterate over\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, results) which must be called once it \n has completed with an error (which can be null) and an array of results.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array containing\n the concatenated results of the iterator function.\n\n__Example__\n\n```js\nasync.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){\n // files is now a list of filenames that exist in the 3 directories\n});\n```\n\n---------------------------------------\n\n\n### concatSeries(arr, iterator, callback)\n\nSame as async.concat, but executes in series instead of parallel.\n\n\n## Control Flow\n\n\n### series(tasks, [callback])\n\nRun an array of functions in series, each one running once the previous\nfunction has completed. If any functions in the series pass an error to its\ncallback, no more functions are run and the callback for the series is\nimmediately called with the value of the error. Once the tasks have completed,\nthe results are passed to the final callback as an array.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final callback as an object\ninstead of an array. This can be a more readable way of handling results from\nasync.series.\n\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed\n a callback(err, result) it must call on completion with an error (which can\n be null) and an optional result value.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the task callbacks.\n\n__Example__\n\n```js\nasync.series([\n function(callback){\n // do some stuff ...\n callback(null, 'one');\n },\n function(callback){\n // do some more stuff ...\n callback(null, 'two');\n }\n],\n// optional callback\nfunction(err, results){\n // results is now equal to ['one', 'two']\n});\n\n\n// an example using an object instead of an array\nasync.series({\n one: function(callback){\n setTimeout(function(){\n callback(null, 1);\n }, 200);\n },\n two: function(callback){\n setTimeout(function(){\n callback(null, 2);\n }, 100);\n }\n},\nfunction(err, results) {\n // results is now equal to: {one: 1, two: 2}\n});\n```\n\n---------------------------------------\n\n\n### parallel(tasks, [callback])\n\nRun an array of functions in parallel, without waiting until the previous\nfunction has completed. If any of the functions pass an error to its\ncallback, the main callback is immediately called with the value of the error.\nOnce the tasks have completed, the results are passed to the final callback as an\narray.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final callback as an object\ninstead of an array. This can be a more readable way of handling results from\nasync.parallel.\n\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed \n a callback(err, result) it must call on completion with an error (which can\n be null) and an optional result value.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the task callbacks.\n\n__Example__\n\n```js\nasync.parallel([\n function(callback){\n setTimeout(function(){\n callback(null, 'one');\n }, 200);\n },\n function(callback){\n setTimeout(function(){\n callback(null, 'two');\n }, 100);\n }\n],\n// optional callback\nfunction(err, results){\n // the results array will equal ['one','two'] even though\n // the second function had a shorter timeout.\n});\n\n\n// an example using an object instead of an array\nasync.parallel({\n one: function(callback){\n setTimeout(function(){\n callback(null, 1);\n }, 200);\n },\n two: function(callback){\n setTimeout(function(){\n callback(null, 2);\n }, 100);\n }\n},\nfunction(err, results) {\n // results is now equals to: {one: 1, two: 2}\n});\n```\n\n---------------------------------------\n\n\n### parallelLimit(tasks, limit, [callback])\n\nThe same as parallel only the tasks are executed in parallel with a maximum of \"limit\" \ntasks executing at any time.\n\nNote that the tasks are not executed in batches, so there is no guarantee that \nthe first \"limit\" tasks will complete before any others are started.\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed \n a callback(err, result) it must call on completion with an error (which can\n be null) and an optional result value.\n* limit - The maximum number of tasks to run at any time.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the task callbacks.\n\n---------------------------------------\n\n\n### whilst(test, fn, callback)\n\nRepeatedly call fn, while test returns true. Calls the callback when stopped,\nor an error occurs.\n\n__Arguments__\n\n* test() - synchronous truth test to perform before each execution of fn.\n* fn(callback) - A function to call each time the test passes. The function is\n passed a callback(err) which must be called once it has completed with an \n optional error argument.\n* callback(err) - A callback which is called after the test fails and repeated\n execution of fn has stopped.\n\n__Example__\n\n```js\nvar count = 0;\n\nasync.whilst(\n function () { return count < 5; },\n function (callback) {\n count++;\n setTimeout(callback, 1000);\n },\n function (err) {\n // 5 seconds have passed\n }\n);\n```\n\n---------------------------------------\n\n\n### doWhilst(fn, test, callback)\n\nThe post check version of whilst. To reflect the difference in the order of operations `test` and `fn` arguments are switched. `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.\n\n---------------------------------------\n\n\n### until(test, fn, callback)\n\nRepeatedly call fn, until test returns true. Calls the callback when stopped,\nor an error occurs.\n\nThe inverse of async.whilst.\n\n---------------------------------------\n\n\n### doUntil(fn, test, callback)\n\nLike doWhilst except the test is inverted. Note the argument ordering differs from `until`.\n\n---------------------------------------\n\n\n### forever(fn, callback)\n\nCalls the asynchronous function 'fn' repeatedly, in series, indefinitely.\nIf an error is passed to fn's callback then 'callback' is called with the\nerror, otherwise it will never be called.\n\n---------------------------------------\n\n\n### waterfall(tasks, [callback])\n\nRuns an array of functions in series, each passing their results to the next in\nthe array. However, if any of the functions pass an error to the callback, the\nnext function is not executed and the main callback is immediately called with\nthe error.\n\n__Arguments__\n\n* tasks - An array of functions to run, each function is passed a \n callback(err, result1, result2, ...) it must call on completion. The first\n argument is an error (which can be null) and any further arguments will be \n passed as arguments in order to the next task.\n* callback(err, [results]) - An optional callback to run once all the functions\n have completed. This will be passed the results of the last task's callback.\n\n\n\n__Example__\n\n```js\nasync.waterfall([\n function(callback){\n callback(null, 'one', 'two');\n },\n function(arg1, arg2, callback){\n callback(null, 'three');\n },\n function(arg1, callback){\n // arg1 now equals 'three'\n callback(null, 'done');\n }\n], function (err, result) {\n // result now equals 'done' \n});\n```\n\n---------------------------------------\n\n### compose(fn1, fn2...)\n\nCreates a function which is a composition of the passed asynchronous\nfunctions. Each function consumes the return value of the function that\nfollows. Composing functions f(), g() and h() would produce the result of\nf(g(h())), only this version uses callbacks to obtain the return values.\n\nEach function is executed with the `this` binding of the composed function.\n\n__Arguments__\n\n* functions... - the asynchronous functions to compose\n\n\n__Example__\n\n```js\nfunction add1(n, callback) {\n setTimeout(function () {\n callback(null, n + 1);\n }, 10);\n}\n\nfunction mul3(n, callback) {\n setTimeout(function () {\n callback(null, n * 3);\n }, 10);\n}\n\nvar add1mul3 = async.compose(mul3, add1);\n\nadd1mul3(4, function (err, result) {\n // result now equals 15\n});\n```\n\n---------------------------------------\n\n### applyEach(fns, args..., callback)\n\nApplies the provided arguments to each function in the array, calling the\ncallback after all functions have completed. If you only provide the first\nargument then it will return a function which lets you pass in the\narguments as if it were a single function call.\n\n__Arguments__\n\n* fns - the asynchronous functions to all call with the same arguments\n* args... - any number of separate arguments to pass to the function\n* callback - the final argument should be the callback, called when all\n functions have completed processing\n\n\n__Example__\n\n```js\nasync.applyEach([enableSearch, updateSchema], 'bucket', callback);\n\n// partial application example:\nasync.each(\n buckets,\n async.applyEach([enableSearch, updateSchema]),\n callback\n);\n```\n\n---------------------------------------\n\n\n### applyEachSeries(arr, iterator, callback)\n\nThe same as applyEach only the functions are applied in series.\n\n---------------------------------------\n\n\n### queue(worker, concurrency)\n\nCreates a queue object with the specified concurrency. Tasks added to the\nqueue will be processed in parallel (up to the concurrency limit). If all\nworkers are in progress, the task is queued until one is available. Once\na worker has completed a task, the task's callback is called.\n\n__Arguments__\n\n* worker(task, callback) - An asynchronous function for processing a queued\n task, which must call its callback(err) argument when finished, with an \n optional error as an argument.\n* concurrency - An integer for determining how many worker functions should be\n run in parallel.\n\n__Queue objects__\n\nThe queue object returned by this function has the following properties and\nmethods:\n\n* length() - a function returning the number of items waiting to be processed.\n* concurrency - an integer for determining how many worker functions should be\n run in parallel. This property can be changed after a queue is created to\n alter the concurrency on-the-fly.\n* push(task, [callback]) - add a new task to the queue, the callback is called\n once the worker has finished processing the task.\n instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.\n* unshift(task, [callback]) - add a new task to the front of the queue.\n* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued\n* empty - a callback that is called when the last item from the queue is given to a worker\n* drain - a callback that is called when the last item from the queue has returned from the worker\n\n__Example__\n\n```js\n// create a queue object with concurrency 2\n\nvar q = async.queue(function (task, callback) {\n console.log('hello ' + task.name);\n callback();\n}, 2);\n\n\n// assign a callback\nq.drain = function() {\n console.log('all items have been processed');\n}\n\n// add some items to the queue\n\nq.push({name: 'foo'}, function (err) {\n console.log('finished processing foo');\n});\nq.push({name: 'bar'}, function (err) {\n console.log('finished processing bar');\n});\n\n// add some items to the queue (batch-wise)\n\nq.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) {\n console.log('finished processing bar');\n});\n\n// add some items to the front of the queue\n\nq.unshift({name: 'bar'}, function (err) {\n console.log('finished processing bar');\n});\n```\n\n---------------------------------------\n\n\n### cargo(worker, [payload])\n\nCreates a cargo object with the specified payload. Tasks added to the\ncargo will be processed altogether (up to the payload limit). If the\nworker is in progress, the task is queued until it is available. Once\nthe worker has completed some tasks, each callback of those tasks is called.\n\n__Arguments__\n\n* worker(tasks, callback) - An asynchronous function for processing an array of\n queued tasks, which must call its callback(err) argument when finished, with \n an optional error as an argument.\n* payload - An optional integer for determining how many tasks should be\n processed per round; if omitted, the default is unlimited.\n\n__Cargo objects__\n\nThe cargo object returned by this function has the following properties and\nmethods:\n\n* length() - a function returning the number of items waiting to be processed.\n* payload - an integer for determining how many tasks should be\n process per round. This property can be changed after a cargo is created to\n alter the payload on-the-fly.\n* push(task, [callback]) - add a new task to the queue, the callback is called\n once the worker has finished processing the task.\n instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.\n* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued\n* empty - a callback that is called when the last item from the queue is given to a worker\n* drain - a callback that is called when the last item from the queue has returned from the worker\n\n__Example__\n\n```js\n// create a cargo object with payload 2\n\nvar cargo = async.cargo(function (tasks, callback) {\n for(var i=0; i\n### auto(tasks, [callback])\n\nDetermines the best order for running functions based on their requirements.\nEach function can optionally depend on other functions being completed first,\nand each function is run as soon as its requirements are satisfied. If any of\nthe functions pass an error to their callback, that function will not complete\n(so any other functions depending on it will not run) and the main callback\nwill be called immediately with the error. Functions also receive an object\ncontaining the results of functions which have completed so far.\n\nNote, all functions are called with a results object as a second argument, \nso it is unsafe to pass functions in the tasks object which cannot handle the\nextra argument. For example, this snippet of code:\n\n```js\nasync.auto({\n readData: async.apply(fs.readFile, 'data.txt', 'utf-8')\n}, callback);\n```\n\nwill have the effect of calling readFile with the results object as the last\nargument, which will fail:\n\n```js\nfs.readFile('data.txt', 'utf-8', cb, {});\n```\n\nInstead, wrap the call to readFile in a function which does not forward the \nresults object:\n\n```js\nasync.auto({\n readData: function(cb, results){\n fs.readFile('data.txt', 'utf-8', cb);\n }\n}, callback);\n```\n\n__Arguments__\n\n* tasks - An object literal containing named functions or an array of\n requirements, with the function itself the last item in the array. The key\n used for each function or array is used when specifying requirements. The \n function receives two arguments: (1) a callback(err, result) which must be \n called when finished, passing an error (which can be null) and the result of \n the function's execution, and (2) a results object, containing the results of\n the previously executed functions.\n* callback(err, results) - An optional callback which is called when all the\n tasks have been completed. The callback will receive an error as an argument\n if any tasks pass an error to their callback. Results will always be passed\n\tbut if an error occurred, no other tasks will be performed, and the results\n\tobject will only contain partial results.\n \n\n__Example__\n\n```js\nasync.auto({\n get_data: function(callback){\n // async code to get some data\n },\n make_folder: function(callback){\n // async code to create a directory to store a file in\n // this is run at the same time as getting the data\n },\n write_file: ['get_data', 'make_folder', function(callback){\n // once there is some data and the directory exists,\n // write the data to a file in the directory\n callback(null, filename);\n }],\n email_link: ['write_file', function(callback, results){\n // once the file is written let's email a link to it...\n // results.write_file contains the filename returned by write_file.\n }]\n});\n```\n\nThis is a fairly trivial example, but to do this using the basic parallel and\nseries functions would look like this:\n\n```js\nasync.parallel([\n function(callback){\n // async code to get some data\n },\n function(callback){\n // async code to create a directory to store a file in\n // this is run at the same time as getting the data\n }\n],\nfunction(err, results){\n async.series([\n function(callback){\n // once there is some data and the directory exists,\n // write the data to a file in the directory\n },\n function(callback){\n // once the file is written let's email a link to it...\n }\n ]);\n});\n```\n\nFor a complicated series of async tasks using the auto function makes adding\nnew tasks much easier and makes the code more readable.\n\n\n---------------------------------------\n\n\n### iterator(tasks)\n\nCreates an iterator function which calls the next function in the array,\nreturning a continuation to call the next one after that. It's also possible to\n'peek' the next iterator by doing iterator.next().\n\nThis function is used internally by the async module but can be useful when\nyou want to manually control the flow of functions in series.\n\n__Arguments__\n\n* tasks - An array of functions to run.\n\n__Example__\n\n```js\nvar iterator = async.iterator([\n function(){ sys.p('one'); },\n function(){ sys.p('two'); },\n function(){ sys.p('three'); }\n]);\n\nnode> var iterator2 = iterator();\n'one'\nnode> var iterator3 = iterator2();\n'two'\nnode> iterator3();\n'three'\nnode> var nextfn = iterator2.next();\nnode> nextfn();\n'three'\n```\n\n---------------------------------------\n\n\n### apply(function, arguments..)\n\nCreates a continuation function with some arguments already applied, a useful\nshorthand when combined with other control flow functions. Any arguments\npassed to the returned function are added to the arguments originally passed\nto apply.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to automatically apply when the\n continuation is called.\n\n__Example__\n\n```js\n// using apply\n\nasync.parallel([\n async.apply(fs.writeFile, 'testfile1', 'test1'),\n async.apply(fs.writeFile, 'testfile2', 'test2'),\n]);\n\n\n// the same process without using apply\n\nasync.parallel([\n function(callback){\n fs.writeFile('testfile1', 'test1', callback);\n },\n function(callback){\n fs.writeFile('testfile2', 'test2', callback);\n }\n]);\n```\n\nIt's possible to pass any number of additional arguments when calling the\ncontinuation:\n\n```js\nnode> var fn = async.apply(sys.puts, 'one');\nnode> fn('two', 'three');\none\ntwo\nthree\n```\n\n---------------------------------------\n\n\n### nextTick(callback)\n\nCalls the callback on a later loop around the event loop. In node.js this just\ncalls process.nextTick, in the browser it falls back to setImmediate(callback)\nif available, otherwise setTimeout(callback, 0), which means other higher priority\nevents may precede the execution of the callback.\n\nThis is used internally for browser-compatibility purposes.\n\n__Arguments__\n\n* callback - The function to call on a later loop around the event loop.\n\n__Example__\n\n```js\nvar call_order = [];\nasync.nextTick(function(){\n call_order.push('two');\n // call_order now equals ['one','two']\n});\ncall_order.push('one')\n```\n\n\n### times(n, callback)\n\nCalls the callback n times and accumulates results in the same manner\nyou would use with async.map.\n\n__Arguments__\n\n* n - The number of times to run the function.\n* callback - The function to call n times.\n\n__Example__\n\n```js\n// Pretend this is some complicated async factory\nvar createUser = function(id, callback) {\n callback(null, {\n id: 'user' + id\n })\n}\n// generate 5 users\nasync.times(5, function(n, next){\n createUser(n, function(err, user) {\n next(err, user)\n })\n}, function(err, users) {\n // we should now have 5 users\n});\n```\n\n\n### timesSeries(n, callback)\n\nThe same as times only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n\n## Utils\n\n\n### memoize(fn, [hasher])\n\nCaches the results of an async function. When creating a hash to store function\nresults against, the callback is omitted from the hash and an optional hash\nfunction can be used.\n\nThe cache of results is exposed as the `memo` property of the function returned\nby `memoize`.\n\n__Arguments__\n\n* fn - the function you to proxy and cache results from.\n* hasher - an optional function for generating a custom hash for storing\n results, it has all the arguments applied to it apart from the callback, and\n must be synchronous.\n\n__Example__\n\n```js\nvar slow_fn = function (name, callback) {\n // do something\n callback(null, result);\n};\nvar fn = async.memoize(slow_fn);\n\n// fn can now be used as if it were slow_fn\nfn('some name', function () {\n // callback\n});\n```\n\n\n### unmemoize(fn)\n\nUndoes a memoized function, reverting it to the original, unmemoized\nform. Comes handy in tests.\n\n__Arguments__\n\n* fn - the memoized function\n\n\n### log(function, arguments)\n\nLogs the result of an async function to the console. Only works in node.js or\nin browsers that support console.log and console.error (such as FF and Chrome).\nIf multiple arguments are returned from the async function, console.log is\ncalled on each argument in order.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to apply to the function.\n\n__Example__\n\n```js\nvar hello = function(name, callback){\n setTimeout(function(){\n callback(null, 'hello ' + name);\n }, 1000);\n};\n```\n```js\nnode> async.log(hello, 'world');\n'hello world'\n```\n\n---------------------------------------\n\n\n### dir(function, arguments)\n\nLogs the result of an async function to the console using console.dir to\ndisplay the properties of the resulting object. Only works in node.js or\nin browsers that support console.dir and console.error (such as FF and Chrome).\nIf multiple arguments are returned from the async function, console.dir is\ncalled on each argument in order.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to apply to the function.\n\n__Example__\n\n```js\nvar hello = function(name, callback){\n setTimeout(function(){\n callback(null, {hello: name});\n }, 1000);\n};\n```\n```js\nnode> async.dir(hello, 'world');\n{hello: 'world'}\n```\n\n---------------------------------------\n\n\n### noConflict()\n\nChanges the value of async back to its original value, returning a reference to the\nasync object.\n", - "readmeFilename": "README.md", - "homepage": "https://github.com/caolan/async#readme" -} diff --git a/node_modules/hapi/node_modules/boom/.travis.yml b/node_modules/hapi/node_modules/boom/.travis.yml index 047f7e3..c84aade 100755 --- a/node_modules/hapi/node_modules/boom/.travis.yml +++ b/node_modules/hapi/node_modules/boom/.travis.yml @@ -2,4 +2,6 @@ language: node_js node_js: - 0.10 + - 0.12 + - iojs diff --git a/node_modules/hapi/node_modules/boom/LICENSE b/node_modules/hapi/node_modules/boom/LICENSE index 911b97e..3946889 100755 --- a/node_modules/hapi/node_modules/boom/LICENSE +++ b/node_modules/hapi/node_modules/boom/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2012-2013, Walmart. +Copyright (c) 2012-2014, Walmart and other contributors. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -8,17 +8,21 @@ modification, are permitted provided that the following conditions are met: * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Walmart nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + * The names of any contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL WALMART BE LIABLE FOR ANY +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * * * + +The complete list of contributors can be found at: https://github.com/hapijs/boom/graphs/contributors \ No newline at end of file diff --git a/node_modules/hapi/node_modules/boom/Makefile b/node_modules/hapi/node_modules/boom/Makefile deleted file mode 100755 index 884ec6d..0000000 --- a/node_modules/hapi/node_modules/boom/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -test: - @node node_modules/lab/bin/lab -test-cov: - @node node_modules/lab/bin/lab -r threshold -t 100 -test-cov-html: - @node node_modules/lab/bin/lab -r html -o coverage.html -complexity: - @node node_modules/complexity-report/src/cli.js -o complexity.md -f markdown lib - -.PHONY: test test-cov test-cov-html complexity - diff --git a/node_modules/hapi/node_modules/boom/README.md b/node_modules/hapi/node_modules/boom/README.md index 1970b1c..43f1562 100755 --- a/node_modules/hapi/node_modules/boom/README.md +++ b/node_modules/hapi/node_modules/boom/README.md @@ -1,6 +1,583 @@ - -![boom Logo](https://raw.github.com/spumko/boom/master/images/boom.png) +![boom Logo](https://raw.github.com/hapijs/boom/master/images/boom.png) HTTP-friendly error objects -[![Build Status](https://secure.travis-ci.org/spumko/boom.png)](http://travis-ci.org/spumko/boom) +[![Build Status](https://secure.travis-ci.org/hapijs/boom.png)](http://travis-ci.org/hapijs/boom) +[![Current Version](https://img.shields.io/npm/v/boom.svg)](https://www.npmjs.com/package/boom) + +Lead Maintainer: [Adam Bretz](https://github.com/arb) + +**boom** provides a set of utilities for returning HTTP errors. Each utility returns a `Boom` error response +object (instance of `Error`) which includes the following properties: +- `isBoom` - if `true`, indicates this is a `Boom` object instance. +- `isServer` - convenience bool indicating status code >= 500. +- `message` - the error message. +- `output` - the formatted response. Can be directly manipulated after object construction to return a custom + error response. Allowed root keys: + - `statusCode` - the HTTP status code (typically 4xx or 5xx). + - `headers` - an object containing any HTTP headers where each key is a header name and value is the header content. + - `payload` - the formatted object used as the response payload (stringified). Can be directly manipulated but any + changes will be lost + if `reformat()` is called. Any content allowed and by default includes the following content: + - `statusCode` - the HTTP status code, derived from `error.output.statusCode`. + - `error` - the HTTP status message (e.g. 'Bad Request', 'Internal Server Error') derived from `statusCode`. + - `message` - the error message derived from `error.message`. +- inherited `Error` properties. + +The `Boom` object also supports the following method: +- `reformat()` - rebuilds `error.output` using the other object properties. + +## Helper Methods + +### `wrap(error, [statusCode], [message])` + +Decorates an error with the **boom** properties where: +- `error` - the error object to wrap. If `error` is already a **boom** object, returns back the same object. +- `statusCode` - optional HTTP status code. Defaults to `500`. +- `message` - optional message string. If the error already has a message, it adds the message as a prefix. + Defaults to no message. + +```js +var error = new Error('Unexpected input'); +Boom.wrap(error, 400); +``` + +### `create(statusCode, [message], [data])` + +Generates an `Error` object with the **boom** decorations where: +- `statusCode` - an HTTP error code number. Must be greater or equal 400. +- `message` - optional message string. +- `data` - additional error data set to `error.data` property. + +```js +var error = Boom.create(400, 'Bad request', { timestamp: Date.now() }); +``` + +## HTTP 4xx Errors + +### `Boom.badRequest([message], [data])` + +Returns a 400 Bad Request error where: +- `message` - optional message. +- `data` - optional additional error data. + +```js +Boom.badRequest('invalid query'); +``` + +Generates the following response payload: + +```json +{ + "statusCode": 400, + "error": "Bad Request", + "message": "invalid query" +} +``` + +### `Boom.unauthorized([message], [scheme], [attributes])` + +Returns a 401 Unauthorized error where: +- `message` - optional message. +- `scheme` can be one of the following: + - an authentication scheme name + - an array of string values. These values will be separated by ', ' and set to the 'WWW-Authenticate' header. +- `attributes` - an object of values to use while setting the 'WWW-Authenticate' header. This value is only used when `schema` is a string, otherwise it is ignored. Every key/value pair will be included in the 'WWW-Authenticate' in the format of 'key="value"'. `null` and `undefined` will be replaced with an empty string. If `attributes` is set, `message` will be used as the 'error' segment of the 'WWW-Authenticate' header. If `message` is unset, the 'error' segment of the header will not be present and `isMissing` will be true on the error object. + +If either `scheme` or `attributes` are set, the resultant `Boom` object will have the 'WWW-Authenticate' header set for the response. + +```js +Boom.unauthorized('invalid password'); +``` + +Generates the following response: + +```json +"payload": { + "statusCode": 401, + "error": "Unauthorized", + "message": "invalid password" +}, +"headers" {} +``` + +```js +Boom.unauthorized('invalid password', 'sample'); +``` + +Generates the following response: + +```json +"payload": { + "statusCode": 401, + "error": "Unauthorized", + "message": "invalid password" +}, +"headers" { + "WWW-Authenticate": "sample error=\"invalid password\"" +} +``` + +```js +Boom.unauthorized('invalid password', 'sample', { ttl: 0, cache: null, foo: 'bar' }); +``` + +Generates the following response: + +```json +"payload": { + "statusCode": 401, + "error": "Unauthorized", + "message": "invalid password" +}, +"headers" { + "WWW-Authenticate": "sample ttl=\"0\", cache=\"\", foo=\"bar\", error=\"invalid password\"" +} +``` + +### `Boom.forbidden([message], [data])` + +Returns a 403 Forbidden error where: +- `message` - optional message. +- `data` - optional additional error data. + +```js +Boom.forbidden('try again some time'); +``` + +Generates the following response payload: + +```json +{ + "statusCode": 403, + "error": "Forbidden", + "message": "try again some time" +} +``` + +### `Boom.notFound([message], [data])` + +Returns a 404 Not Found error where: +- `message` - optional message. +- `data` - optional additional error data. + +```js +Boom.notFound('missing'); +``` + +Generates the following response payload: + +```json +{ + "statusCode": 404, + "error": "Not Found", + "message": "missing" +} +``` + +### `Boom.methodNotAllowed([message], [data])` + +Returns a 405 Method Not Allowed error where: +- `message` - optional message. +- `data` - optional additional error data. + +```js +Boom.methodNotAllowed('that method is not allowed'); +``` + +Generates the following response payload: + +```json +{ + "statusCode": 405, + "error": "Method Not Allowed", + "message": "that method is not allowed" +} +``` + +### `Boom.notAcceptable([message], [data])` + +Returns a 406 Not Acceptable error where: +- `message` - optional message. +- `data` - optional additional error data. + +```js +Boom.notAcceptable('unacceptable'); +``` + +Generates the following response payload: + +```json +{ + "statusCode": 406, + "error": "Not Acceptable", + "message": "unacceptable" +} +``` + +### `Boom.proxyAuthRequired([message], [data])` + +Returns a 407 Proxy Authentication Required error where: +- `message` - optional message. +- `data` - optional additional error data. + +```js +Boom.proxyAuthRequired('auth missing'); +``` + +Generates the following response payload: + +```json +{ + "statusCode": 407, + "error": "Proxy Authentication Required", + "message": "auth missing" +} +``` + +### `Boom.clientTimeout([message], [data])` + +Returns a 408 Request Time-out error where: +- `message` - optional message. +- `data` - optional additional error data. + +```js +Boom.clientTimeout('timed out'); +``` + +Generates the following response payload: + +```json +{ + "statusCode": 408, + "error": "Request Time-out", + "message": "timed out" +} +``` + +### `Boom.conflict([message], [data])` + +Returns a 409 Conflict error where: +- `message` - optional message. +- `data` - optional additional error data. + +```js +Boom.conflict('there was a conflict'); +``` + +Generates the following response payload: + +```json +{ + "statusCode": 409, + "error": "Conflict", + "message": "there was a conflict" +} +``` + +### `Boom.resourceGone([message], [data])` + +Returns a 410 Gone error where: +- `message` - optional message. +- `data` - optional additional error data. + +```js +Boom.resourceGone('it is gone'); +``` + +Generates the following response payload: + +```json +{ + "statusCode": 410, + "error": "Gone", + "message": "it is gone" +} +``` + +### `Boom.lengthRequired([message], [data])` + +Returns a 411 Length Required error where: +- `message` - optional message. +- `data` - optional additional error data. + +```js +Boom.lengthRequired('length needed'); +``` + +Generates the following response payload: + +```json +{ + "statusCode": 411, + "error": "Length Required", + "message": "length needed" +} +``` + +### `Boom.preconditionFailed([message], [data])` + +Returns a 412 Precondition Failed error where: +- `message` - optional message. +- `data` - optional additional error data. + +```js +Boom.preconditionFailed(); +``` + +Generates the following response payload: + +```json +{ + "statusCode": 412, + "error": "Precondition Failed" +} +``` + +### `Boom.entityTooLarge([message], [data])` + +Returns a 413 Request Entity Too Large error where: +- `message` - optional message. +- `data` - optional additional error data. + +```js +Boom.entityTooLarge('too big'); +``` + +Generates the following response payload: + +```json +{ + "statusCode": 413, + "error": "Request Entity Too Large", + "message": "too big" +} +``` + +### `Boom.uriTooLong([message], [data])` + +Returns a 414 Request-URI Too Large error where: +- `message` - optional message. +- `data` - optional additional error data. + +```js +Boom.uriTooLong('uri is too long'); +``` + +Generates the following response payload: + +```json +{ + "statusCode": 414, + "error": "Request-URI Too Large", + "message": "uri is too long" +} +``` + +### `Boom.unsupportedMediaType([message], [data])` + +Returns a 415 Unsupported Media Type error where: +- `message` - optional message. +- `data` - optional additional error data. + +```js +Boom.unsupportedMediaType('that media is not supported'); +``` + +Generates the following response payload: + +```json +{ + "statusCode": 415, + "error": "Unsupported Media Type", + "message": "that media is not supported" +} +``` + +### `Boom.rangeNotSatisfiable([message], [data])` + +Returns a 416 Requested Range Not Satisfiable error where: +- `message` - optional message. +- `data` - optional additional error data. + +```js +Boom.rangeNotSatisfiable(); +``` + +Generates the following response payload: + +```json +{ + "statusCode": 416, + "error": "Requested Range Not Satisfiable" +} +``` + +### `Boom.expectationFailed([message], [data])` + +Returns a 417 Expectation Failed error where: +- `message` - optional message. +- `data` - optional additional error data. + +```js +Boom.expectationFailed('expected this to work'); +``` + +Generates the following response payload: + +```json +{ + "statusCode": 417, + "error": "Expectation Failed", + "message": "expected this to work" +} +``` + +### `Boom.badData([message], [data])` + +Returns a 422 Unprocessable Entity error where: +- `message` - optional message. +- `data` - optional additional error data. + +```js +Boom.badData('your data is bad and you should feel bad'); +``` + +Generates the following response payload: + +```json +{ + "statusCode": 422, + "error": "Unprocessable Entity", + "message": "your data is bad and you should feel bad" +} +``` + +### `Boom.tooManyRequests([message], [data])` + +Returns a 429 Too Many Requests error where: +- `message` - optional message. +- `data` - optional additional error data. + +```js +Boom.tooManyRequests('you have exceeded your request limit'); +``` + +Generates the following response payload: + +```json +{ + "statusCode": 429, + "error": "Too Many Requests", + "message": "you have exceeded your request limit" +} +``` + +## HTTP 5xx Errors + +All 500 errors hide your message from the end user. Your message is recorded in the server log. + +### `Boom.notImplemented([message], [data])` + +Returns a 501 Not Implemented error where: +- `message` - optional message. +- `data` - optional additional error data. + +```js +Boom.notImplemented('method not implemented'); +``` + +Generates the following response payload: + +```json +{ + "statusCode": 501, + "error": "Not Implemented", + "message": "method not implemented" +} +``` + +### `Boom.badGateway([message], [data])` + +Returns a 502 Bad Gateway error where: +- `message` - optional message. +- `data` - optional additional error data. + +```js +Boom.badGateway('that is a bad gateway'); +``` + +Generates the following response payload: + +```json +{ + "statusCode": 502, + "error": "Bad Gateway", + "message": "that is a bad gateway" +} +``` + +### `Boom.serverTimeout([message], [data])` + +Returns a 503 Service Unavailable error where: +- `message` - optional message. +- `data` - optional additional error data. + +```js +Boom.serverTimeout('unavailable'); +``` + +Generates the following response payload: + +```json +{ + "statusCode": 503, + "error": "Service Unavailable", + "message": "unavailable" +} +``` + +### `Boom.gatewayTimeout([message], [data])` + +Returns a 504 Gateway Time-out error where: +- `message` - optional message. +- `data` - optional additional error data. + +```js +Boom.gatewayTimeout(); +``` + +Generates the following response payload: + +```json +{ + "statusCode": 504, + "error": "Gateway Time-out" +} +``` + +### `Boom.badImplementation([message], [data])` + +Returns a 500 Internal Server Error error where: +- `message` - optional message. +- `data` - optional additional error data. + +```js +Boom.badImplementation('terrible implementation'); +``` + +Generates the following response payload: + +```json +{ + "statusCode": 500, + "error": "Internal Server Error", + "message": "An internal server error occurred" +} +``` + +## F.A.Q. + +###### How do I include extra information in my responses? `output.payload` is missing `data`, what gives? + +There is a reason the values passed back in the response payloads are pretty locked down. It's mostly for security and to not leak any important information back to the client. This means you will need to put in a little more effort to include extra information about your custom error. Check out the ["Error transformation"](https://github.com/hapijs/hapi/blob/master/API.md#error-transformation) section in the hapi documentation. diff --git a/node_modules/hapi/node_modules/boom/package.json b/node_modules/hapi/node_modules/boom/package.json index 82a718a..963bc79 100644 --- a/node_modules/hapi/node_modules/boom/package.json +++ b/node_modules/hapi/node_modules/boom/package.json @@ -1,16 +1,10 @@ { "name": "boom", "description": "HTTP-friendly error objects", - "version": "0.4.2", - "author": { - "name": "Eran Hammer", - "email": "eran@hueniverse.com", - "url": "http://hueniverse.com" - }, - "contributors": [], + "version": "2.7.2", "repository": { "type": "git", - "url": "git://github.com/spumko/boom.git" + "url": "git://github.com/hapijs/boom.git" }, "main": "index", "keywords": [ @@ -21,27 +15,50 @@ "node": ">=0.8.0" }, "dependencies": { - "hoek": "0.9.x" + "hoek": "2.x.x" }, "devDependencies": { - "lab": "0.1.x", - "complexity-report": "0.x.x" + "code": "1.x.x", + "lab": "5.x.x" }, "scripts": { - "test": "make test-cov" + "test": "lab -a code -t 100", + "test-cov-html": "lab -a code -r html -o coverage.html" + }, + "license": "BSD-3-Clause", + "gitHead": "29be188e9ecfce3a2e090b8714dec2b6e0791724", + "bugs": { + "url": "https://github.com/hapijs/boom/issues" + }, + "homepage": "https://github.com/hapijs/boom", + "_id": "boom@2.7.2", + "_shasum": "dad628d897f7fd2e32cc82197f13307971cf8354", + "_from": "boom@2.7.2", + "_npmVersion": "2.7.0", + "_nodeVersion": "0.10.38", + "_npmUser": { + "name": "arb", + "email": "arbretz@gmail.com" }, - "licenses": [ + "maintainers": [ { - "type": "BSD", - "url": "http://github.com/spumko/boom/raw/master/LICENSE" + "name": "hueniverse", + "email": "eran@hueniverse.com" + }, + { + "name": "wyatt", + "email": "wpreul@gmail.com" + }, + { + "name": "arb", + "email": "arbretz@gmail.com" } ], - "readme": "\n![boom Logo](https://raw.github.com/spumko/boom/master/images/boom.png)\n\nHTTP-friendly error objects\n\n[![Build Status](https://secure.travis-ci.org/spumko/boom.png)](http://travis-ci.org/spumko/boom)\n", - "readmeFilename": "README.md", - "bugs": { - "url": "https://github.com/spumko/boom/issues" + "dist": { + "shasum": "dad628d897f7fd2e32cc82197f13307971cf8354", + "tarball": "http://registry.npmjs.org/boom/-/boom-2.7.2.tgz" }, - "homepage": "https://github.com/spumko/boom", - "_id": "boom@0.4.2", - "_from": "boom@>=0.4.0 <0.5.0" + "directories": {}, + "_resolved": "https://registry.npmjs.org/boom/-/boom-2.7.2.tgz", + "readme": "ERROR: No README data found!" } diff --git a/node_modules/hapi/node_modules/boom/test/index.js b/node_modules/hapi/node_modules/boom/test/index.js index a20c1c3..a0db4df 100755 --- a/node_modules/hapi/node_modules/boom/test/index.js +++ b/node_modules/hapi/node_modules/boom/test/index.js @@ -1,7 +1,9 @@ // Load modules -var Lab = require('lab'); +var Util = require('util'); +var Code = require('code'); var Boom = require('../lib'); +var Lab = require('lab'); // Declare internals @@ -11,235 +13,603 @@ var internals = {}; // Test shortcuts -var expect = Lab.expect; -var before = Lab.before; -var after = Lab.after; -var describe = Lab.experiment; -var it = Lab.test; +var lab = exports.lab = Lab.script(); +var describe = lab.describe; +var it = lab.it; +var expect = Code.expect; + + +it('returns the same object when already boom', function (done) { + + var error = Boom.badRequest(); + var wrapped = Boom.wrap(error); + expect(error).to.equal(wrapped); + done(); +}); + +it('returns an error with info when constructed using another error', function (done) { + + var error = new Error('ka-boom'); + error.xyz = 123; + var err = Boom.wrap(error); + expect(err.xyz).to.equal(123); + expect(err.message).to.equal('ka-boom'); + expect(err.output).to.deep.equal({ + statusCode: 500, + payload: { + statusCode: 500, + error: 'Internal Server Error', + message: 'An internal server error occurred' + }, + headers: {} + }); + expect(err.data).to.equal(null); + done(); +}); + +it('does not override data when constructed using another error', function (done) { + + var error = new Error('ka-boom'); + error.data = { useful: 'data' }; + var err = Boom.wrap(error); + expect(err.data).to.equal(error.data); + done(); +}); + +it('sets new message when none exists', function (done) { + + var error = new Error(); + var wrapped = Boom.wrap(error, 400, 'something bad'); + expect(wrapped.message).to.equal('something bad'); + done(); +}); + +it('throws when statusCode is not a number', function (done) { + + expect(function () { + + Boom.create('x'); + }).to.throw('First argument must be a number (400+): x'); + done(); +}); + +it('will cast a number-string to an integer', function (done) { + + var codes = [ + { input: '404', result: 404 }, + { input: '404.1', result: 404 }, + { input: 400, result: 400 }, + { input: 400.123, result: 400 }] + for (var i = 0, il = codes.length; i < il; ++i) { + var code = codes[i]; + var err = Boom.create(code.input); + expect(err.output.statusCode).to.equal(code.result); + } + + done(); +}); + +it('throws when statusCode is not finite', function (done) { + expect(function () { + + Boom.create(1 / 0); + }).to.throw('First argument must be a number (400+): null'); + done(); +}); + +it('sets error code to unknown', function (done) { + + var err = Boom.create(999); + expect(err.output.payload.error).to.equal('Unknown'); + done(); +}); -describe('Boom', function () { +describe('create()', function () { - it('returns an error with info when constructed using another error', function (done) { + it('does not sets null message', function (done) { - var error = new Error('ka-boom'); - error.xyz = 123; - var err = new Boom(error); - expect(err.data.xyz).to.equal(123); - expect(err.message).to.equal('ka-boom'); - expect(err.response).to.deep.equal({ - code: 500, - payload: { - code: 500, - error: 'Internal Server Error', - message: 'ka-boom' - }, - headers: {} - }); + var error = Boom.unauthorized(null); + expect(error.output.payload.message).to.not.exist(); + expect(error.isServer).to.be.false(); done(); }); - describe('#isBoom', function () { + it('sets message and data', function (done) { - it('returns true for Boom object', function (done) { + var error = Boom.badRequest('Missing data', { type: 'user' }); + expect(error.data.type).to.equal('user'); + expect(error.output.payload.message).to.equal('Missing data'); + done(); + }); +}); - expect(Boom.badRequest().isBoom).to.equal(true); - done(); - }); +describe('isBoom()', function () { - it('returns false for Error object', function (done) { + it('returns true for Boom object', function (done) { - expect(new Error().isBoom).to.not.exist; - done(); - }); + expect(Boom.badRequest().isBoom).to.equal(true); + done(); }); - describe('#badRequest', function () { + it('returns false for Error object', function (done) { - it('returns a 400 error code', function (done) { + expect((new Error()).isBoom).to.not.exist(); + done(); + }); +}); - expect(Boom.badRequest().response.code).to.equal(400); - done(); - }); +describe('badRequest()', function () { - it('sets the message with the passed in message', function (done) { + it('returns a 400 error statusCode', function (done) { - expect(Boom.badRequest('my message').message).to.equal('my message'); - done(); - }); + var error = Boom.badRequest(); + + expect(error.output.statusCode).to.equal(400); + expect(error.isServer).to.be.false(); + done(); }); - describe('#unauthorized', function () { + it('sets the message with the passed in message', function (done) { - it('returns a 401 error code', function (done) { + expect(Boom.badRequest('my message').message).to.equal('my message'); + done(); + }); - var err = Boom.unauthorized(); - expect(err.response.code).to.equal(401); - expect(err.response.headers).to.deep.equal({}); - done(); - }); + it('sets the message to HTTP status if none provided', function (done) { - it('sets the message with the passed in message', function (done) { + expect(Boom.badRequest().message).to.equal('Bad Request'); + done(); + }); +}); - expect(Boom.unauthorized('my message').message).to.equal('my message'); - done(); - }); +describe('unauthorized()', function () { - it('returns a WWW-Authenticate header when passed a scheme', function (done) { + it('returns a 401 error statusCode', function (done) { - var err = Boom.unauthorized('boom', 'Test'); - expect(err.response.code).to.equal(401); - expect(err.response.headers['WWW-Authenticate']).to.equal('Test error="boom"'); - done(); - }); + var err = Boom.unauthorized(); + expect(err.output.statusCode).to.equal(401); + expect(err.output.headers).to.deep.equal({}); + done(); + }); - it('returns a WWW-Authenticate header when passed a scheme and attributes', function (done) { + it('sets the message with the passed in message', function (done) { - var err = Boom.unauthorized('boom', 'Test', { a: 1, b: 'something', c: null, d: 0 }); - expect(err.response.code).to.equal(401); - expect(err.response.headers['WWW-Authenticate']).to.equal('Test a="1", b="something", c="", d="0", error="boom"'); - done(); - }); + expect(Boom.unauthorized('my message').message).to.equal('my message'); + done(); + }); - it('sets the isMissing flag when error message is empty', function (done) { + it('returns a WWW-Authenticate header when passed a scheme', function (done) { - var err = Boom.unauthorized('', 'Basic'); - expect(err.isMissing).to.equal(true); - done(); - }); + var err = Boom.unauthorized('boom', 'Test'); + expect(err.output.statusCode).to.equal(401); + expect(err.output.headers['WWW-Authenticate']).to.equal('Test error="boom"'); + done(); + }); - it('does not set the isMissing flag when error message is not empty', function (done) { + it('returns a WWW-Authenticate header set to the schema array value', function (done) { - var err = Boom.unauthorized('message', 'Basic'); - expect(err.isMissing).to.equal(undefined); - done(); - }); + var err = Boom.unauthorized(null, ['Test','one','two']); + expect(err.output.statusCode).to.equal(401); + expect(err.output.headers['WWW-Authenticate']).to.equal('Test, one, two'); + done(); + }); - it('sets a WWW-Authenticate when passed as an array', function (done) { + it('returns a WWW-Authenticate header when passed a scheme and attributes', function (done) { - var err = Boom.unauthorized('message', ['Basic', 'Example e="1"', 'Another x="3", y="4"']); - expect(err.response.headers['WWW-Authenticate']).to.equal('Basic, Example e="1", Another x="3", y="4"'); - done(); - }); + var err = Boom.unauthorized('boom', 'Test', { a: 1, b: 'something', c: null, d: 0 }); + expect(err.output.statusCode).to.equal(401); + expect(err.output.headers['WWW-Authenticate']).to.equal('Test a="1", b="something", c="", d="0", error="boom"'); + done(); }); - describe('#clientTimeout', function () { + it('returns a WWW-Authenticate header when passed attributes, missing error', function (done) { - it('returns a 408 error code', function (done) { + var err = Boom.unauthorized(null, 'Test', { a: 1, b: 'something', c: null, d: 0 }); + expect(err.output.statusCode).to.equal(401); + expect(err.output.headers['WWW-Authenticate']).to.equal('Test a="1", b="something", c="", d="0"'); + expect(err.isMissing).to.equal(true); + done(); + }); - expect(Boom.clientTimeout().response.code).to.equal(408); - done(); - }); + it('sets the isMissing flag when error message is empty', function (done) { - it('sets the message with the passed in message', function (done) { + var err = Boom.unauthorized('', 'Basic'); + expect(err.isMissing).to.equal(true); + done(); + }); - expect(Boom.clientTimeout('my message').message).to.equal('my message'); - done(); - }); + it('does not set the isMissing flag when error message is not empty', function (done) { + + var err = Boom.unauthorized('message', 'Basic'); + expect(err.isMissing).to.equal(undefined); + done(); }); - describe('#serverTimeout', function () { + it('sets a WWW-Authenticate when passed as an array', function (done) { - it('returns a 503 error code', function (done) { + var err = Boom.unauthorized('message', ['Basic', 'Example e="1"', 'Another x="3", y="4"']); + expect(err.output.headers['WWW-Authenticate']).to.equal('Basic, Example e="1", Another x="3", y="4"'); + done(); + }); +}); - expect(Boom.serverTimeout().response.code).to.equal(503); - done(); - }); - it('sets the message with the passed in message', function (done) { +describe('methodNotAllowed()', function () { - expect(Boom.serverTimeout('my message').message).to.equal('my message'); - done(); - }); + it('returns a 405 error statusCode', function (done) { + + expect(Boom.methodNotAllowed().output.statusCode).to.equal(405); + done(); }); - describe('#forbidden', function () { + it('sets the message with the passed in message', function (done) { + + expect(Boom.methodNotAllowed('my message').message).to.equal('my message'); + done(); + }); +}); - it('returns a 403 error code', function (done) { - expect(Boom.forbidden().response.code).to.equal(403); - done(); - }); +describe('notAcceptable()', function () { - it('sets the message with the passed in message', function (done) { + it('returns a 406 error statusCode', function (done) { - expect(Boom.forbidden('my message').message).to.equal('my message'); - done(); - }); + expect(Boom.notAcceptable().output.statusCode).to.equal(406); + done(); }); - describe('#notFound', function () { + it('sets the message with the passed in message', function (done) { - it('returns a 404 error code', function (done) { + expect(Boom.notAcceptable('my message').message).to.equal('my message'); + done(); + }); +}); - expect(Boom.notFound().response.code).to.equal(404); - done(); - }); - it('sets the message with the passed in message', function (done) { +describe('proxyAuthRequired()', function () { - expect(Boom.notFound('my message').message).to.equal('my message'); - done(); - }); + it('returns a 407 error statusCode', function (done) { + + expect(Boom.proxyAuthRequired().output.statusCode).to.equal(407); + done(); }); - describe('#internal', function () { + it('sets the message with the passed in message', function (done) { - it('returns a 500 error code', function (done) { + expect(Boom.proxyAuthRequired('my message').message).to.equal('my message'); + done(); + }); +}); - expect(Boom.internal().response.code).to.equal(500); - done(); - }); - it('sets the message with the passed in message', function (done) { +describe('clientTimeout()', function () { - var err = Boom.internal('my message'); - expect(err.message).to.equal('my message'); - expect(err.response.payload.message).to.equal('An internal server error occurred'); - done(); - }); + it('returns a 408 error statusCode', function (done) { - it('passes data on the callback if its passed in', function (done) { + expect(Boom.clientTimeout().output.statusCode).to.equal(408); + done(); + }); - expect(Boom.internal('my message', { my: 'data' }).data.my).to.equal('data'); - done(); - }); + it('sets the message with the passed in message', function (done) { + + expect(Boom.clientTimeout('my message').message).to.equal('my message'); + done(); + }); +}); - it('uses passed in stack if its available', function (done) { - var error = new Error(); - error.stack = 'my stack line\nmy second stack line'; - expect(Boom.internal('my message', error).trace[0]).to.equal('my stack line'); - done(); - }); +describe('conflict()', function () { + + it('returns a 409 error statusCode', function (done) { + + expect(Boom.conflict().output.statusCode).to.equal(409); + done(); }); - describe('#passThrough', function () { + it('sets the message with the passed in message', function (done) { - it('returns a pass-through error', function (done) { + expect(Boom.conflict('my message').message).to.equal('my message'); + done(); + }); +}); - var err = Boom.passThrough(499, { a: 1 }, 'application/text', { 'X-Test': 'Boom' }); - expect(err.response.code).to.equal(499); - expect(err.message).to.equal('Pass-through'); - expect(err.response).to.deep.equal({ - code: 499, - payload: { a: 1 }, - headers: { 'X-Test': 'Boom' }, - type: 'application/text' - }); - done(); - }); + +describe('resourceGone()', function () { + + it('returns a 410 error statusCode', function (done) { + + expect(Boom.resourceGone().output.statusCode).to.equal(410); + done(); + }); + + it('sets the message with the passed in message', function (done) { + + expect(Boom.resourceGone('my message').message).to.equal('my message'); + done(); }); +}); + - describe('#reformat', function () { +describe('lengthRequired()', function () { + + it('returns a 411 error statusCode', function (done) { + + expect(Boom.lengthRequired().output.statusCode).to.equal(411); + done(); + }); + + it('sets the message with the passed in message', function (done) { + + expect(Boom.lengthRequired('my message').message).to.equal('my message'); + done(); + }); +}); - it('encodes any HTML markup in the response payload', function (done) { - var boom = new Boom(new Error('')); - expect(boom.response.payload.message).to.not.contain('')); - expect(boom.response.payload.message).to.not.contain(''); - expect(encoded).to.equal('\\x3cscript\\x3ealert\\x281\\x29\\x3c\\x2fscript\\x3e'); - done(); - }); - - it('encodes \' characters', function (done) { - - var encoded = Hoek.escapeJavaScript('something(\'param\')'); - expect(encoded).to.equal('something\\x28\\x27param\\x27\\x29'); - done(); - }); - - it('encodes large unicode characters with the correct padding', function (done) { - - var encoded = Hoek.escapeJavaScript(String.fromCharCode(500) + String.fromCharCode(1000)); - expect(encoded).to.equal('\\u0500\\u1000'); - done(); - }); - - it('doesn\'t throw an exception when passed null', function (done) { - - var encoded = Hoek.escapeJavaScript(null); - expect(encoded).to.equal(''); - done(); - }); - }); - - describe('#escapeHtml', function () { - - it('encodes / characters', function (done) { - - var encoded = Hoek.escapeHtml(''); - expect(encoded).to.equal('<script>alert(1)</script>'); - done(); - }); - - it('encodes < and > as named characters', function (done) { - - var encoded = Hoek.escapeHtml(''); - expect(encoded).to.equal('\\x3cscript\\x3ealert\\x281\\x29\\x3c\\x2fscript\\x3e'); - done(); - }); - - it('encodes \' characters', function (done) { - - var encoded = Hoek.escapeJavaScript('something(\'param\')'); - expect(encoded).to.equal('something\\x28\\x27param\\x27\\x29'); - done(); - }); - - it('encodes large unicode characters with the correct padding', function (done) { - - var encoded = Hoek.escapeJavaScript(String.fromCharCode(500) + String.fromCharCode(1000)); - expect(encoded).to.equal('\\u0500\\u1000'); - done(); - }); - - it('doesn\'t throw an exception when passed null', function (done) { - - var encoded = Hoek.escapeJavaScript(null); - expect(encoded).to.equal(''); - done(); - }); -}); - -describe('escapeHtml()', function () { - - it('encodes / characters', function (done) { - - var encoded = Hoek.escapeHtml(''); - expect(encoded).to.equal('<script>alert(1)</script>'); - done(); - }); - - it('encodes < and > as named characters', function (done) { - - var encoded = Hoek.escapeHtml(''); - expect(encoded).to.equal('\\x3cscript\\x3ealert\\x281\\x29\\x3c\\x2fscript\\x3e'); - done(); - }); + var encoded = Hoek.escapeJavaScript(''); + expect(encoded).to.equal('\\x3cscript\\x3ealert\\x281\\x29\\x3c\\x2fscript\\x3e'); + done(); + }); - it('encodes \' characters', function (done) { + it('encodes \' characters', function (done) { - var encoded = Hoek.escapeJavaScript('something(\'param\')'); - expect(encoded).to.equal('something\\x28\\x27param\\x27\\x29'); - done(); - }); + var encoded = Hoek.escapeJavaScript('something(\'param\')'); + expect(encoded).to.equal('something\\x28\\x27param\\x27\\x29'); + done(); + }); - it('encodes large unicode characters with the correct padding', function (done) { + it('encodes large unicode characters with the correct padding', function (done) { - var encoded = Hoek.escapeJavaScript(String.fromCharCode(500) + String.fromCharCode(1000)); - expect(encoded).to.equal('\\u0500\\u1000'); - done(); - }); + var encoded = Hoek.escapeJavaScript(String.fromCharCode(500) + String.fromCharCode(1000)); + expect(encoded).to.equal('\\u0500\\u1000'); + done(); + }); - it('doesn\'t throw an exception when passed null', function (done) { + it('doesn\'t throw an exception when passed null', function (done) { - var encoded = Hoek.escapeJavaScript(null); - expect(encoded).to.equal(''); - done(); - }); + var encoded = Hoek.escapeJavaScript(null); + expect(encoded).to.equal(''); + done(); }); +}); - describe('#escapeHtml', function () { +describe('escapeHtml()', function () { - it('encodes / characters', function (done) { + it('encodes / characters', function (done) { - var encoded = Hoek.escapeHtml(''); - expect(encoded).to.equal('<script>alert(1)</script>'); - done(); - }); + var encoded = Hoek.escapeHtml(''); + expect(encoded).to.equal('<script>alert(1)</script>'); + done(); + }); - it('encodes < and > as named characters', function (done) { + it('encodes < and > as named characters', function (done) { - var encoded = Hoek.escapeHtml(';' } }, - function (res) { - - expect(res.result.message).to.not.exist; - done(); - }); - }); - - it('doesn\'t exist with invalid cookie values in the request', function (done) { - - server.inject({ - method: 'POST', - url: '/', - payload: '{"something":"something"}', - headers: { 'cookie': 'encoded="";' } }, - function (res) { - - expect(res.result.message).to.not.contain('', 'seomthing'); - }}); - - server.inject({ - method: 'GET', - url: '/cookiename' }, - function (res) { - - expect(res.result.message).to.not.contain(''); - }}); - - server.inject({ - method: 'GET', - url: '/cookievalue' }, - function (res) { - - expect(res.result.message).to.not.contain('"}', - headers: { 'content-type': 'application/json' } }, - function (res) { - - expect(res.result.message).to.not.contain('' }, - function (res) { - - expect(res.result.message).to.not.contain(' + + + \ No newline at end of file diff --git a/public/css/styles.css b/public/css/styles.css new file mode 100644 index 0000000..46b6127 --- /dev/null +++ b/public/css/styles.css @@ -0,0 +1,3 @@ +html { + font-family: Arial, Helvetica, sans-serif +} \ No newline at end of file diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..eccb246 --- /dev/null +++ b/public/index.html @@ -0,0 +1,18 @@ + + + + + + Runners Tracker + + +
    +
  • + {{ runner.name }} * +
  • +
+ + + + + \ No newline at end of file diff --git a/public/js/app.js b/public/js/app.js new file mode 100644 index 0000000..266e6c6 --- /dev/null +++ b/public/js/app.js @@ -0,0 +1,68 @@ +var rta = angular.module('runApp',[]); + +rta.controller('indexController', ['$scope', '$interval', 'dataFactory', function($scope, $interval, dataFactory) { + + $interval(function(){ + + dataFactory.getTop().success(function (top) { + $scope.top = top; + }) + + },1000); + + $scope.getTimes=function(n){ + return new Array(n); + }; + + + +}]); + +rta.controller('adminController', ['$scope', 'dataFactory', function($scope, dataFactory) { + dataFactory.getRunners().success(function (runners) { + $scope.runners = runners; + }) + + dataFactory.getLaps().success(function (laps) { + $scope.laps = laps; + }) + +}]); + + +rta.factory('dataFactory', ['$http', function($http) { + + var urlBase = '/'; + var dataFactory = {}; + + dataFactory.getRunners = function () { + return $http.get(urlBase + 'runners'); + }; + + dataFactory.getRunnerByID = function (bid) { + return $http.get(urlBase + 'runners?bid=' + bid); + }; + + dataFactory.addRunner = function (runner) { + return $http.post(urlBase + 'runners', runner); + }; + + dataFactory.getLaps = function () { + return $http.get(urlBase + 'laps') + }; + + dataFactory.getLapsByID = function (bid) { + return $http.get(urlBase + 'laps?bid=' + bid); + }; + + dataFactory.addLaps = function (lap) { + return $http.post(urlBase + 'laps', lap); + }; + + dataFactory.getTop = function (top) { + return $http.get(urlBase + 'top'); + }; + + return dataFactory; +}]); + diff --git a/public/js/vendor/angular.min.js b/public/js/vendor/angular.min.js new file mode 100644 index 0000000..1fefca2 --- /dev/null +++ b/public/js/vendor/angular.min.js @@ -0,0 +1,289 @@ +/* + AngularJS v1.4.0 + (c) 2010-2015 Google, Inc. http://angularjs.org + License: MIT +*/ +(function(N,W,u){'use strict';function F(b){return function(){var a=arguments[0],c;c="["+(b?b+":":"")+a+"] http://errors.angularjs.org/1.4.0/"+(b?b+"/":"")+a;for(a=1;a").append(b).html();try{return b[0].nodeType===ab?E(c):c.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+E(b)})}catch(d){return E(c)}}function xc(b){try{return decodeURIComponent(b)}catch(a){}}function yc(b){var a={},c,d;n((b||"").split("&"),function(b){b&&(c=b.replace(/\+/g,"%20").split("="),d=xc(c[0]),y(d)&&(b=y(c[1])?xc(c[1]):!0,kb.call(a,d)?K(a[d])? +a[d].push(b):a[d]=[a[d],b]:a[d]=b))});return a}function Qb(b){var a=[];n(b,function(b,d){K(b)?n(b,function(b){a.push(ia(d,!0)+(!0===b?"":"="+ia(b,!0)))}):a.push(ia(d,!0)+(!0===b?"":"="+ia(b,!0)))});return a.length?a.join("&"):""}function mb(b){return ia(b,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function ia(b,a){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g,a?"%20":"+")} +function Xd(b,a){var c,d,e=Na.length;for(d=0;d/,">"));}a=a||[];a.unshift(["$provide",function(a){a.value("$rootElement",b)}]);c.debugInfoEnabled&&a.push(["$compileProvider",function(a){a.debugInfoEnabled(!0)}]);a.unshift("ng");d=bb(a,c.strictDi);d.invoke(["$rootScope","$rootElement","$compile","$injector",function(a,b,c,d){a.$apply(function(){b.data("$injector",d);c(b)(a)})}]);return d},e=/^NG_ENABLE_DEBUG_INFO!/,f=/^NG_DEFER_BOOTSTRAP!/;N&&e.test(N.name)&&(c.debugInfoEnabled= +!0,N.name=N.name.replace(e,""));if(N&&!f.test(N.name))return d();N.name=N.name.replace(f,"");aa.resumeBootstrap=function(b){n(b,function(b){a.push(b)});return d()};G(aa.resumeDeferredBootstrap)&&aa.resumeDeferredBootstrap()}function Zd(){N.name="NG_ENABLE_DEBUG_INFO!"+N.name;N.location.reload()}function $d(b){b=aa.element(b).injector();if(!b)throw Ea("test");return b.get("$$testability")}function Ac(b,a){a=a||"_";return b.replace(ae,function(b,d){return(d?a:"")+b.toLowerCase()})}function be(){var b; +if(!Bc){var a=nb();la=N.jQuery;y(a)&&(la=null===a?u:N[a]);la&&la.fn.on?(z=la,Q(la.fn,{scope:Oa.scope,isolateScope:Oa.isolateScope,controller:Oa.controller,injector:Oa.injector,inheritedData:Oa.inheritedData}),b=la.cleanData,la.cleanData=function(a){var d;if(Rb)Rb=!1;else for(var e=0,f;null!=(f=a[e]);e++)(d=la._data(f,"events"))&&d.$destroy&&la(f).triggerHandler("$destroy");b(a)}):z=R;aa.element=z;Bc=!0}}function Sb(b,a,c){if(!b)throw Ea("areq",a||"?",c||"required");return b}function Pa(b,a,c){c&& +K(b)&&(b=b[b.length-1]);Sb(G(b),a,"not a function, got "+(b&&"object"===typeof b?b.constructor.name||"Object":typeof b));return b}function Qa(b,a){if("hasOwnProperty"===b)throw Ea("badname",a);}function Cc(b,a,c){if(!a)return b;a=a.split(".");for(var d,e=b,f=a.length,g=0;g")+d[2];for(d= +d[0];d--;)c=c.lastChild;f=Za(f,c.childNodes);c=e.firstChild;c.textContent=""}else f.push(a.createTextNode(b));e.textContent="";e.innerHTML="";n(f,function(a){e.appendChild(a)});return e}function R(b){if(b instanceof R)return b;var a;L(b)&&(b=T(b),a=!0);if(!(this instanceof R)){if(a&&"<"!=b.charAt(0))throw Ub("nosel");return new R(b)}if(a){a=W;var c;b=(c=Cf.exec(b))?[a.createElement(c[1])]:(c=Mc(b,a))?c.childNodes:[]}Nc(this,b)}function Vb(b){return b.cloneNode(!0)}function rb(b,a){a||sb(b);if(b.querySelectorAll)for(var c= +b.querySelectorAll("*"),d=0,e=c.length;dk&&this.remove(s.key); +return b}},get:function(a){if(k").parent()[0])});var f=P(a,b,a,c,d,e);S.$$addScopeClass(a);var g=null;return function(b,c,d){Sb(b,"scope");d=d||{};var e=d.parentBoundTranscludeFn,h=d.transcludeControllers; +d=d.futureParentElement;e&&e.$$boundTransclude&&(e=e.$$boundTransclude);g||(g=(d=d&&d[0])?"foreignobject"!==ta(d)&&d.toString().match(/SVG/)?"svg":"html":"html");d="html"!==g?z(Yb(g,z("
").append(a).html())):c?Oa.clone.call(a):a;if(h)for(var l in h)d.data("$"+l+"Controller",h[l].instance);S.$$addScopeInfo(d,b);c&&c(d,b);f&&f(b,d,d,e);return d}}function P(a,b,c,d,e,f){function g(a,c,d,e){var f,l,k,m,s,B,A;if(p)for(A=Array(c.length),m=0;mJ.priority)break;if(v=J.scope)J.templateUrl||(C(v)?(N("new/isolated scope",t||O,J,X),t=J):N("new/isolated scope",t,J,X)),O=O||J;w=J.name;!J.templateUrl&&J.controller&&(v=J.controller,ba=ba||ga(),N("'"+w+"' controller",ba[w],J,X),ba[w]=J);if(v=J.transclude)x=!0,J.$$tlb||(N("transclusion", +n,J,X),n=J),"element"==v?(q=!0,P=J.priority,v=X,X=d.$$element=z(W.createComment(" "+w+": "+d[w]+" ")),b=X[0],U(f,ra.call(v,0),b),Ja=S(v,e,P,g&&g.name,{nonTlbTranscludeDirective:n})):(v=z(Vb(b)).contents(),X.empty(),Ja=S(v,e));if(J.template)if(I=!0,N("template",D,J,X),D=J,v=G(J.template)?J.template(X,d):J.template,v=fa(v),J.replace){g=J;v=Tb.test(v)?Zc(Yb(J.templateNamespace,T(v))):[];b=v[0];if(1!=v.length||b.nodeType!==pa)throw ea("tplrt",w,"");U(f,X,b);E={$attr:{}};v=ha(b,[],E);var R=a.splice(F+ +1,a.length-(F+1));t&&y(v);a=a.concat(v).concat(R);$c(d,E);E=a.length}else X.html(v);if(J.templateUrl)I=!0,N("template",D,J,X),D=J,J.replace&&(g=J),M=Kf(a.splice(F,a.length-F),X,d,f,x&&Ja,h,k,{controllerDirectives:ba,newIsolateScopeDirective:t,templateDirective:D,nonTlbTranscludeDirective:n}),E=a.length;else if(J.compile)try{za=J.compile(X,d,Ja),G(za)?s(null,za,Ab,Q):za&&s(za.pre,za.post,Ab,Q)}catch(V){c(V,va(X))}J.terminal&&(M.terminal=!0,P=Math.max(P,J.priority))}M.scope=O&&!0===O.scope;M.transcludeOnThisElement= +x;M.elementTranscludeOnThisElement=q;M.templateOnThisElement=I;M.transclude=Ja;m.hasElementTranscludeDirective=q;return M}function y(a){for(var b=0,c=a.length;bm.priority)&&-1!=m.restrict.indexOf(f)&&(l&&(m=Ob(m,{$$start:l,$$end:k})),b.push(m),h=m)}catch(A){c(A)}}return h}function F(b){if(e.hasOwnProperty(b))for(var c= +a.get(b+"Directive"),d=0,f=c.length;d"+b+"";return c.childNodes[0].childNodes;default:return b}}function R(a,b){if("srcdoc"==b)return I.HTML;var c=ta(a);if("xlinkHref"==b||"form"==c&&"action"==b||"img"!=c&&("src"==b||"ngSrc"==b))return I.RESOURCE_URL}function V(a,c,d,e,f){var g=R(a,e);f=h[e]||f;var l=b(d,!0,g,f);if(l){if("multiple"===e&&"select"===ta(a))throw ea("selmulti",va(a));c.push({priority:100,compile:function(){return{pre:function(a,c,h){c=h.$$observers||(h.$$observers={});if(k.test(e))throw ea("nodomevents"); +var m=h[e];m!==d&&(l=m&&b(m,!0,g,f),d=m);l&&(h[e]=l(a),(c[e]||(c[e]=[])).$$inter=!0,(h.$$observers&&h.$$observers[e].$$scope||a).$watch(l,function(a,b){"class"===e&&a!=b?h.$updateClass(a,b):h.$set(e,a)}))}}}})}}function U(a,b,c){var d=b[0],e=b.length,f=d.parentNode,g,h;if(a)for(g=0,h=a.length;g=a)return b;for(;a--;)8===b[a].nodeType&&Lf.call(b,a,1);return b}function We(){var b={},a=!1;this.register=function(a,d){Qa(a,"controller");C(a)?Q(b,a):b[a]=d};this.allowGlobals=function(){a=!0};this.$get=["$injector","$window",function(c,d){function e(a,b,c,d){if(!a||!C(a.$scope))throw F("$controller")("noscp",d,b);a.$scope[b]=c}return function(f, +g,h,l){var k,m,r;h=!0===h;l&&L(l)&&(r=l);if(L(f)){l=f.match(Wc);if(!l)throw Mf("ctrlfmt",f);m=l[1];r=r||l[3];f=b.hasOwnProperty(m)?b[m]:Cc(g.$scope,m,!0)||(a?Cc(d,m,!0):u);Pa(f,m,!0)}if(h)return h=(K(f)?f[f.length-1]:f).prototype,k=Object.create(h||null),r&&e(g,r,k,m||f.name),Q(function(){var a=c.invoke(f,k,g,m);a!==k&&(C(a)||G(a))&&(k=a,r&&e(g,r,k,m||f.name));return k},{instance:k,identifier:r});k=c.instantiate(f,g,m);r&&e(g,r,k,m||f.name);return k}}]}function Xe(){this.$get=["$window",function(b){return z(b.document)}]} +function Ye(){this.$get=["$log",function(b){return function(a,c){b.error.apply(b,arguments)}}]}function Zb(b){return C(b)?da(b)?b.toISOString():$a(b):b}function bf(){this.$get=function(){return function(b){if(!b)return"";var a=[];oc(b,function(b,d){null===b||v(b)||(K(b)?n(b,function(b,c){a.push(ia(d)+"="+ia(Zb(b)))}):a.push(ia(d)+"="+ia(Zb(b))))});return a.join("&")}}}function cf(){this.$get=function(){return function(b){function a(b,e,f){null===b||v(b)||(K(b)?n(b,function(b){a(b,e+"[]")}):C(b)&& +!da(b)?oc(b,function(b,c){a(b,e+(f?"":"[")+c+(f?"":"]"))}):c.push(ia(e)+"="+ia(Zb(b))))}if(!b)return"";var c=[];a(b,"",!0);return c.join("&")}}}function $b(b,a){if(L(b)){var c=b.replace(Nf,"").trim();if(c){var d=a("Content-Type");(d=d&&0===d.indexOf(bd))||(d=(d=c.match(Of))&&Pf[d[0]].test(c));d&&(b=vc(c))}}return b}function cd(b){var a=ga(),c;L(b)?n(b.split("\n"),function(b){c=b.indexOf(":");var e=E(T(b.substr(0,c)));b=T(b.substr(c+1));e&&(a[e]=a[e]?a[e]+", "+b:b)}):C(b)&&n(b,function(b,c){var f= +E(c),g=T(b);f&&(a[f]=a[f]?a[f]+", "+g:g)});return a}function dd(b){var a;return function(c){a||(a=cd(b));return c?(c=a[E(c)],void 0===c&&(c=null),c):a}}function ed(b,a,c,d){if(G(d))return d(b,a,c);n(d,function(d){b=d(b,a,c)});return b}function af(){var b=this.defaults={transformResponse:[$b],transformRequest:[function(a){return C(a)&&"[object File]"!==sa.call(a)&&"[object Blob]"!==sa.call(a)&&"[object FormData]"!==sa.call(a)?$a(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"},post:fa(ac), +put:fa(ac),patch:fa(ac)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",paramSerializer:"$httpParamSerializer"},a=!1;this.useApplyAsync=function(b){return y(b)?(a=!!b,this):a};var c=this.interceptors=[];this.$get=["$httpBackend","$$cookieReader","$cacheFactory","$rootScope","$q","$injector",function(d,e,f,g,h,l){function k(a){function c(a){var b=Q({},a);b.data=a.data?ed(a.data,a.headers,a.status,e.transformResponse):a.data;a=a.status;return 200<=a&&300>a?b:h.reject(b)}function d(a,b){var c, +e={};n(a,function(a,d){G(a)?(c=a(b),null!=c&&(e[d]=c)):e[d]=a});return e}if(!aa.isObject(a))throw F("$http")("badreq",a);var e=Q({method:"get",transformRequest:b.transformRequest,transformResponse:b.transformResponse,paramSerializer:b.paramSerializer},a);e.headers=function(a){var c=b.headers,e=Q({},a.headers),f,g,h,c=Q({},c.common,c[E(a.method)]);a:for(f in c){g=E(f);for(h in e)if(E(h)===g)continue a;e[f]=c[f]}return d(e,fa(a))}(a);e.method=pb(e.method);e.paramSerializer=L(e.paramSerializer)?l.get(e.paramSerializer): +e.paramSerializer;var f=[function(a){var d=a.headers,e=ed(a.data,dd(d),u,a.transformRequest);v(e)&&n(d,function(a,b){"content-type"===E(b)&&delete d[b]});v(a.withCredentials)&&!v(b.withCredentials)&&(a.withCredentials=b.withCredentials);return m(a,e).then(c,c)},u],g=h.when(e);for(n(A,function(a){(a.request||a.requestError)&&f.unshift(a.request,a.requestError);(a.response||a.responseError)&&f.push(a.response,a.responseError)});f.length;){a=f.shift();var k=f.shift(),g=g.then(a,k)}g.success=function(a){Pa(a, +"fn");g.then(function(b){a(b.data,b.status,b.headers,e)});return g};g.error=function(a){Pa(a,"fn");g.then(null,function(b){a(b.data,b.status,b.headers,e)});return g};return g}function m(c,f){function l(b,c,d,e){function f(){m(c,b,d,e)}O&&(200<=b&&300>b?O.put(P,[b,c,cd(d),e]):O.remove(P));a?g.$applyAsync(f):(f(),g.$$phase||g.$apply())}function m(a,b,d,e){b=Math.max(b,0);(200<=b&&300>b?I.resolve:I.reject)({data:a,status:b,headers:dd(d),config:c,statusText:e})}function A(a){m(a.data,a.status,fa(a.headers()), +a.statusText)}function n(){var a=k.pendingRequests.indexOf(c);-1!==a&&k.pendingRequests.splice(a,1)}var I=h.defer(),B=I.promise,O,D,S=c.headers,P=r(c.url,c.paramSerializer(c.params));k.pendingRequests.push(c);B.then(n,n);!c.cache&&!b.cache||!1===c.cache||"GET"!==c.method&&"JSONP"!==c.method||(O=C(c.cache)?c.cache:C(b.cache)?b.cache:s);O&&(D=O.get(P),y(D)?D&&G(D.then)?D.then(A,A):K(D)?m(D[1],D[0],fa(D[2]),D[3]):m(D,200,{},"OK"):O.put(P,B));v(D)&&((D=fd(c.url)?e()[c.xsrfCookieName||b.xsrfCookieName]: +u)&&(S[c.xsrfHeaderName||b.xsrfHeaderName]=D),d(c.method,P,f,l,S,c.timeout,c.withCredentials,c.responseType));return B}function r(a,b){0=l&&(t.resolve(H),A(p.$$intervalId),delete f[p.$$intervalId]);M||b.$apply()},h);f[p.$$intervalId]=t;return p}var f={};e.cancel=function(b){return b&&b.$$intervalId in +f?(f[b.$$intervalId].reject("canceled"),a.clearInterval(b.$$intervalId),delete f[b.$$intervalId],!0):!1};return e}]}function fe(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2,maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")",gSize:3,lgSize:3}],CURRENCY_SYM:"$"},DATETIME_FORMATS:{MONTH:"January February March April May June July August September October November December".split(" "), +SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy",mediumTime:"h:mm:ss a",shortTime:"h:mm a",ERANAMES:["Before Christ","Anno Domini"],ERAS:["BC","AD"]},pluralCat:function(b){return 1===b?"one":"other"}}}} +function bc(b){b=b.split("/");for(var a=b.length;a--;)b[a]=mb(b[a]);return b.join("/")}function gd(b,a){var c=Aa(b);a.$$protocol=c.protocol;a.$$host=c.hostname;a.$$port=Y(c.port)||Sf[c.protocol]||null}function hd(b,a){var c="/"!==b.charAt(0);c&&(b="/"+b);var d=Aa(b);a.$$path=decodeURIComponent(c&&"/"===d.pathname.charAt(0)?d.pathname.substring(1):d.pathname);a.$$search=yc(d.search);a.$$hash=decodeURIComponent(d.hash);a.$$path&&"/"!=a.$$path.charAt(0)&&(a.$$path="/"+a.$$path)}function ya(b,a){if(0=== +a.indexOf(b))return a.substr(b.length)}function Ia(b){var a=b.indexOf("#");return-1==a?b:b.substr(0,a)}function Bb(b){return b.replace(/(#.+)|#$/,"$1")}function cc(b){return b.substr(0,Ia(b).lastIndexOf("/")+1)}function dc(b,a){this.$$html5=!0;a=a||"";var c=cc(b);gd(b,this);this.$$parse=function(a){var b=ya(c,a);if(!L(b))throw Cb("ipthprfx",a,c);hd(b,this);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var a=Qb(this.$$search),b=this.$$hash?"#"+mb(this.$$hash):"";this.$$url= +bc(this.$$path)+(a?"?"+a:"")+b;this.$$absUrl=c+this.$$url.substr(1)};this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;(f=ya(b,d))!==u?(g=f,g=(f=ya(a,f))!==u?c+(ya("/",f)||f):b+g):(f=ya(c,d))!==u?g=c+f:c==d+"/"&&(g=c);g&&this.$$parse(g);return!!g}}function ec(b,a){var c=cc(b);gd(b,this);this.$$parse=function(d){d=ya(b,d)||ya(c,d);var e;"#"===d.charAt(0)?(e=ya(a,d),v(e)&&(e=d)):e=this.$$html5?d:"";hd(e,this);d=this.$$path;var f=/^\/[A-Z]:(\/.*)/;0===e.indexOf(b)&& +(e=e.replace(b,""));f.exec(e)||(d=(e=f.exec(d))?e[1]:d);this.$$path=d;this.$$compose()};this.$$compose=function(){var c=Qb(this.$$search),e=this.$$hash?"#"+mb(this.$$hash):"";this.$$url=bc(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+(this.$$url?a+this.$$url:"")};this.$$parseLinkUrl=function(a,c){return Ia(b)==Ia(a)?(this.$$parse(a),!0):!1}}function id(b,a){this.$$html5=!0;ec.apply(this,arguments);var c=cc(b);this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f, +g;b==Ia(d)?f=d:(g=ya(c,d))?f=b+a+g:c===d+"/"&&(f=c);f&&this.$$parse(f);return!!f};this.$$compose=function(){var c=Qb(this.$$search),e=this.$$hash?"#"+mb(this.$$hash):"";this.$$url=bc(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+a+this.$$url}}function Db(b){return function(){return this[b]}}function jd(b,a){return function(c){if(v(c))return this[b];this[b]=a(c);this.$$compose();return this}}function ef(){var b="",a={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(a){return y(a)? +(b=a,this):b};this.html5Mode=function(b){return Xa(b)?(a.enabled=b,this):C(b)?(Xa(b.enabled)&&(a.enabled=b.enabled),Xa(b.requireBase)&&(a.requireBase=b.requireBase),Xa(b.rewriteLinks)&&(a.rewriteLinks=b.rewriteLinks),this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement","$window",function(c,d,e,f,g){function h(a,b,c){var e=k.url(),f=k.$$state;try{d.url(a,b,c),k.$$state=d.state()}catch(g){throw k.url(e),k.$$state=f,g;}}function l(a,b){c.$broadcast("$locationChangeSuccess",k.absUrl(), +a,k.$$state,b)}var k,m;m=d.baseHref();var r=d.url(),s;if(a.enabled){if(!m&&a.requireBase)throw Cb("nobase");s=r.substring(0,r.indexOf("/",r.indexOf("//")+2))+(m||"/");m=e.history?dc:id}else s=Ia(r),m=ec;k=new m(s,"#"+b);k.$$parseLinkUrl(r,r);k.$$state=d.state();var A=/^\s*(javascript|mailto):/i;f.on("click",function(b){if(a.rewriteLinks&&!b.ctrlKey&&!b.metaKey&&!b.shiftKey&&2!=b.which&&2!=b.button){for(var e=z(b.target);"a"!==ta(e[0]);)if(e[0]===f[0]||!(e=e.parent())[0])return;var h=e.prop("href"), +l=e.attr("href")||e.attr("xlink:href");C(h)&&"[object SVGAnimatedString]"===h.toString()&&(h=Aa(h.animVal).href);A.test(h)||!h||e.attr("target")||b.isDefaultPrevented()||!k.$$parseLinkUrl(h,l)||(b.preventDefault(),k.absUrl()!=d.url()&&(c.$apply(),g.angular["ff-684208-preventDefault"]=!0))}});Bb(k.absUrl())!=Bb(r)&&d.url(k.absUrl(),!0);var H=!0;d.onUrlChange(function(a,b){c.$evalAsync(function(){var d=k.absUrl(),e=k.$$state,f;k.$$parse(a);k.$$state=b;f=c.$broadcast("$locationChangeStart",a,d,b,e).defaultPrevented; +k.absUrl()===a&&(f?(k.$$parse(d),k.$$state=e,h(d,!1,e)):(H=!1,l(d,e)))});c.$$phase||c.$digest()});c.$watch(function(){var a=Bb(d.url()),b=Bb(k.absUrl()),f=d.state(),g=k.$$replace,m=a!==b||k.$$html5&&e.history&&f!==k.$$state;if(H||m)H=!1,c.$evalAsync(function(){var b=k.absUrl(),d=c.$broadcast("$locationChangeStart",b,a,k.$$state,f).defaultPrevented;k.absUrl()===b&&(d?(k.$$parse(a),k.$$state=f):(m&&h(b,g,f===k.$$state?null:k.$$state),l(a,f)))});k.$$replace=!1});return k}]}function ff(){var b=!0,a=this; +this.debugEnabled=function(a){return y(a)?(b=a,this):b};this.$get=["$window",function(c){function d(a){a instanceof Error&&(a.stack?a=a.message&&-1===a.stack.indexOf(a.message)?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=c.console||{},e=b[a]||b.log||w;a=!1;try{a=!!e.apply}catch(l){}return a?function(){var a=[];n(arguments,function(b){a.push(d(b))});return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"), +info:e("info"),warn:e("warn"),error:e("error"),debug:function(){var c=e("debug");return function(){b&&c.apply(a,arguments)}}()}}]}function Ba(b,a){if("__defineGetter__"===b||"__defineSetter__"===b||"__lookupGetter__"===b||"__lookupSetter__"===b||"__proto__"===b)throw ca("isecfld",a);return b}function na(b,a){if(b){if(b.constructor===b)throw ca("isecfn",a);if(b.window===b)throw ca("isecwindow",a);if(b.children&&(b.nodeName||b.prop&&b.attr&&b.find))throw ca("isecdom",a);if(b===Object)throw ca("isecobj", +a);}return b}function kd(b,a){if(b){if(b.constructor===b)throw ca("isecfn",a);if(b===Tf||b===Uf||b===Vf)throw ca("isecff",a);}}function Wf(b,a){return"undefined"!==typeof b?b:a}function ld(b,a){return"undefined"===typeof b?a:"undefined"===typeof a?b:b+a}function U(b,a){var c,d;switch(b.type){case q.Program:c=!0;n(b.body,function(b){U(b.expression,a);c=c&&b.expression.constant});b.constant=c;break;case q.Literal:b.constant=!0;b.toWatch=[];break;case q.UnaryExpression:U(b.argument,a);b.constant=b.argument.constant; +b.toWatch=b.argument.toWatch;break;case q.BinaryExpression:U(b.left,a);U(b.right,a);b.constant=b.left.constant&&b.right.constant;b.toWatch=b.left.toWatch.concat(b.right.toWatch);break;case q.LogicalExpression:U(b.left,a);U(b.right,a);b.constant=b.left.constant&&b.right.constant;b.toWatch=b.constant?[]:[b];break;case q.ConditionalExpression:U(b.test,a);U(b.alternate,a);U(b.consequent,a);b.constant=b.test.constant&&b.alternate.constant&&b.consequent.constant;b.toWatch=b.constant?[]:[b];break;case q.Identifier:b.constant= +!1;b.toWatch=[b];break;case q.MemberExpression:U(b.object,a);b.computed&&U(b.property,a);b.constant=b.object.constant&&(!b.computed||b.property.constant);b.toWatch=[b];break;case q.CallExpression:c=b.filter?!a(b.callee.name).$stateful:!1;d=[];n(b.arguments,function(b){U(b,a);c=c&&b.constant;b.constant||d.push.apply(d,b.toWatch)});b.constant=c;b.toWatch=b.filter&&!a(b.callee.name).$stateful?d:[b];break;case q.AssignmentExpression:U(b.left,a);U(b.right,a);b.constant=b.left.constant&&b.right.constant; +b.toWatch=[b];break;case q.ArrayExpression:c=!0;d=[];n(b.elements,function(b){U(b,a);c=c&&b.constant;b.constant||d.push.apply(d,b.toWatch)});b.constant=c;b.toWatch=d;break;case q.ObjectExpression:c=!0;d=[];n(b.properties,function(b){U(b.value,a);c=c&&b.value.constant;b.value.constant||d.push.apply(d,b.value.toWatch)});b.constant=c;b.toWatch=d;break;case q.ThisExpression:b.constant=!1,b.toWatch=[]}}function md(b){if(1==b.length){b=b[0].expression;var a=b.toWatch;return 1!==a.length?a:a[0]!==b?a:u}} +function nd(b){return b.type===q.Identifier||b.type===q.MemberExpression}function od(b){if(1===b.body.length&&nd(b.body[0].expression))return{type:q.AssignmentExpression,left:b.body[0].expression,right:{type:q.NGValueParameter},operator:"="}}function pd(b){return 0===b.body.length||1===b.body.length&&(b.body[0].expression.type===q.Literal||b.body[0].expression.type===q.ArrayExpression||b.body[0].expression.type===q.ObjectExpression)}function qd(b,a){this.astBuilder=b;this.$filter=a}function rd(b, +a){this.astBuilder=b;this.$filter=a}function Eb(b,a,c,d){na(b,d);a=a.split(".");for(var e,f=0;1=this.promise.$$state.status&&d&&d.length&&b(function(){for(var b,e,f=0,g=d.length;fa)for(b in k++,f)e.hasOwnProperty(b)||(n--,delete f[b])}else f!==e&&(f=e,k++);return k}}c.$stateful=!0;var d=this,e,f,g,l=1n&&(I=4-n,t[I]||(t[I]=[]),t[I].push({msg:G(b.exp)?"fn: "+(b.exp.name||b.exp.toString()):b.exp,newVal:f,oldVal:h}));else if(b=== +d){s=!1;break a}}catch(z){g(z)}if(!(k=A.$$watchersCount&&A.$$childHead||A!==this&&A.$$nextSibling))for(;A!==this&&!(k=A.$$nextSibling);)A=A.$parent}while(A=k);if((s||x.length)&&!n--)throw p.$$phase=null,c("infdig",a,t);}while(s||x.length);for(p.$$phase=null;y.length;)try{y.shift()()}catch(C){g(C)}},$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;this===p&&l.$$applicationDestroyed();s(this,-this.$$watchersCount);for(var b in this.$$listenerCount)A(this, +this.$$listenerCount[b],b);a&&a.$$childHead==this&&(a.$$childHead=this.$$nextSibling);a&&a.$$childTail==this&&(a.$$childTail=this.$$prevSibling);this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=this.$$nextSibling);this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling);this.$destroy=this.$digest=this.$apply=this.$evalAsync=this.$applyAsync=w;this.$on=this.$watch=this.$watchGroup=function(){return w};this.$$listeners={};this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead= +this.$$childTail=this.$root=this.$$watchers=null}},$eval:function(a,b){return h(a)(this,b)},$evalAsync:function(a,b){p.$$phase||x.length||l.defer(function(){x.length&&p.$digest()});x.push({scope:this,expression:a,locals:b})},$$postDigest:function(a){y.push(a)},$apply:function(a){try{return r("$apply"),this.$eval(a)}catch(b){g(b)}finally{p.$$phase=null;try{p.$digest()}catch(c){throw g(c),c;}}},$applyAsync:function(a){function b(){c.$eval(a)}var c=this;a&&I.push(b);t()},$on:function(a,b){var c=this.$$listeners[a]; +c||(this.$$listeners[a]=c=[]);c.push(b);var d=this;do d.$$listenerCount[a]||(d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);var e=this;return function(){var d=c.indexOf(b);-1!==d&&(c[d]=null,A(e,1,a))}},$emit:function(a,b){var c=[],d,e=this,f=!1,h={name:a,targetScope:e,stopPropagation:function(){f=!0},preventDefault:function(){h.defaultPrevented=!0},defaultPrevented:!1},l=Za([h],arguments,1),k,m;do{d=e.$$listeners[a]||c;h.currentScope=e;k=0;for(m=d.length;kgb)throw Ca("iequirks");var d=fa(oa);d.isEnabled=function(){return b};d.trustAs= +c.trustAs;d.getTrusted=c.getTrusted;d.valueOf=c.valueOf;b||(d.trustAs=d.getTrusted=function(a,b){return b},d.valueOf=Ua);d.parseAs=function(b,c){var e=a(c);return e.literal&&e.constant?e:a(c,function(a){return d.getTrusted(b,a)})};var e=d.parseAs,f=d.getTrusted,g=d.trustAs;n(oa,function(a,b){var c=E(b);d[eb("parse_as_"+c)]=function(b){return e(a,b)};d[eb("get_trusted_"+c)]=function(b){return f(a,b)};d[eb("trust_as_"+c)]=function(b){return g(a,b)}});return d}]}function nf(){this.$get=["$window","$document", +function(b,a){var c={},d=Y((/android (\d+)/.exec(E((b.navigator||{}).userAgent))||[])[1]),e=/Boxee/i.test((b.navigator||{}).userAgent),f=a[0]||{},g,h=/^(Moz|webkit|ms)(?=[A-Z])/,l=f.body&&f.body.style,k=!1,m=!1;if(l){for(var r in l)if(k=h.exec(r)){g=k[0];g=g.substr(0,1).toUpperCase()+g.substr(1);break}g||(g="WebkitOpacity"in l&&"webkit");k=!!("transition"in l||g+"Transition"in l);m=!!("animation"in l||g+"Animation"in l);!d||k&&m||(k=L(l.webkitTransition),m=L(l.webkitAnimation))}return{history:!(!b.history|| +!b.history.pushState||4>d||e),hasEvent:function(a){if("input"===a&&11>=gb)return!1;if(v(c[a])){var b=f.createElement("div");c[a]="on"+a in b}return c[a]},csp:cb(),vendorPrefix:g,transitions:k,animations:m,android:d}}]}function pf(){this.$get=["$templateCache","$http","$q",function(b,a,c){function d(e,f){d.totalPendingRequests++;var g=a.defaults&&a.defaults.transformResponse;K(g)?g=g.filter(function(a){return a!==$b}):g===$b&&(g=null);return a.get(e,{cache:b,transformResponse:g})["finally"](function(){d.totalPendingRequests--}).then(function(a){b.put(e, +a.data);return a.data},function(a){if(!f)throw ea("tpload",e,a.status,a.statusText);return c.reject(a)})}d.totalPendingRequests=0;return d}]}function qf(){this.$get=["$rootScope","$browser","$location",function(b,a,c){return{findBindings:function(a,b,c){a=a.getElementsByClassName("ng-binding");var g=[];n(a,function(a){var d=aa.element(a).data("$binding");d&&n(d,function(d){c?(new RegExp("(^|\\s)"+td(b)+"(\\s|\\||$)")).test(d)&&g.push(a):-1!=d.indexOf(b)&&g.push(a)})});return g},findModels:function(a, +b,c){for(var g=["ng-","data-ng-","ng\\:"],h=0;hb;b=Math.abs(b);var g=Infinity=== +b;if(!g&&!isFinite(b))return"";var h=b+"",l="",k=!1,m=[];g&&(l="\u221e");if(!g&&-1!==h.indexOf("e")){var r=h.match(/([\d\.]+)e(-?)(\d+)/);r&&"-"==r[2]&&r[3]>e+1?b=0:(l=h,k=!0)}if(g||k)0b&&(l=b.toFixed(e),b=parseFloat(l));else{g=(h.split(Cd)[1]||"").length;v(e)&&(e=Math.min(Math.max(a.minFrac,g),a.maxFrac));b=+(Math.round(+(b.toString()+"e"+e)).toString()+"e"+-e);var g=(""+b).split(Cd),h=g[0],g=g[1]||"",r=0,s=a.lgSize,n=a.gSize;if(h.length>=s+n)for(r=h.length-s,k=0;kb&&(d="-",b=-b);for(b=""+b;b.length-c)e+=c;0===e&&-12==c&&(e=12);return Gb(e,a,d)}}function Hb(b,a){return function(c, +d){var e=c["get"+b](),f=pb(a?"SHORT"+b:b);return d[f][e]}}function Dd(b){var a=(new Date(b,0,1)).getDay();return new Date(b,0,(4>=a?5:12)-a)}function Ed(b){return function(a){var c=Dd(a.getFullYear());a=+new Date(a.getFullYear(),a.getMonth(),a.getDate()+(4-a.getDay()))-+c;a=1+Math.round(a/6048E5);return Gb(a,b)}}function jc(b,a){return 0>=b.getFullYear()?a.ERAS[0]:a.ERAS[1]}function yd(b){function a(a){var b;if(b=a.match(c)){a=new Date(0);var f=0,g=0,h=b[8]?a.setUTCFullYear:a.setFullYear,l=b[8]?a.setUTCHours: +a.setHours;b[9]&&(f=Y(b[9]+b[10]),g=Y(b[9]+b[11]));h.call(a,Y(b[1]),Y(b[2])-1,Y(b[3]));f=Y(b[4]||0)-f;g=Y(b[5]||0)-g;h=Y(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));l.call(a,f,g,h,b)}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,e,f){var g="",h=[],l,k;e=e||"mediumDate";e=b.DATETIME_FORMATS[e]||e;L(c)&&(c=eg.test(c)?Y(c):a(c));V(c)&&(c=new Date(c));if(!da(c)||!isFinite(c.getTime()))return c;for(;e;)(k= +fg.exec(e))?(h=Za(h,k,1),e=h.pop()):(h.push(e),e=null);var m=c.getTimezoneOffset();f&&(m=wc(f,c.getTimezoneOffset()),c=Pb(c,f,!0));n(h,function(a){l=gg[a];g+=l?l(c,b.DATETIME_FORMATS,m):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function $f(){return function(b,a){v(a)&&(a=2);return $a(b,a)}}function ag(){return function(b,a,c){a=Infinity===Math.abs(Number(a))?Number(a):Y(a);if(isNaN(a))return b;V(b)&&(b=b.toString());if(!K(b)&&!L(b))return b;c=!c||isNaN(c)?0:Y(c);c=0>c&&c>=-b.length? +b.length+c:c;return 0<=a?b.slice(c,c+a):0===c?b.slice(a,b.length):b.slice(Math.max(0,c+a),c)}}function Ad(b){return function(a,c,d){function e(a,b){return b?function(b,c){return a(c,b)}:a}function f(a){switch(typeof a){case "number":case "boolean":case "string":return!0;default:return!1}}function g(a){return null===a?"null":"function"===typeof a.valueOf&&(a=a.valueOf(),f(a))||"function"===typeof a.toString&&(a=a.toString(),f(a))?a:""}function h(a,b){var c=typeof a,d=typeof b;c===d&&"object"===c&& +(a=g(a),b=g(b));return c===d?("string"===c&&(a=a.toLowerCase(),b=b.toLowerCase()),a===b?0:ab||37<=b&&40>=b||m(a,this,this.value)});if(e.hasEvent("paste"))a.on("paste cut",m)}a.on("change",l);d.$render=function(){a.val(d.$isEmpty(d.$viewValue)?"":d.$viewValue)}}function Kb(b,a){return function(c,d){var e,f;if(da(c))return c;if(L(c)){'"'==c.charAt(0)&&'"'==c.charAt(c.length-1)&&(c=c.substring(1,c.length-1));if(hg.test(c))return new Date(c);b.lastIndex=0;if(e= +b.exec(c))return e.shift(),f=d?{yyyy:d.getFullYear(),MM:d.getMonth()+1,dd:d.getDate(),HH:d.getHours(),mm:d.getMinutes(),ss:d.getSeconds(),sss:d.getMilliseconds()/1E3}:{yyyy:1970,MM:1,dd:1,HH:0,mm:0,ss:0,sss:0},n(e,function(b,c){c=M};g.$observe("min",function(a){M=s(a);h.$validate()})}if(y(g.max)||g.ngMax){var t;h.$validators.max=function(a){return!r(a)|| +v(t)||c(a)<=t};g.$observe("max",function(a){t=s(a);h.$validate()})}}}function Hd(b,a,c,d){(d.$$hasNativeValidators=C(a[0].validity))&&d.$parsers.push(function(b){var c=a.prop("validity")||{};return c.badInput&&!c.typeMismatch?u:b})}function Id(b,a,c,d,e){if(y(d)){b=b(d);if(!b.constant)throw F("ngModel")("constexpr",c,d);return b(a)}return e}function lc(b,a){b="ngClass"+b;return["$animate",function(c){function d(a,b){var c=[],d=0;a:for(;d(?:<\/\1>|)$/, +Tb=/<|&#?\w+;/,Af=/<([\w:]+)/,Bf=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ma={option:[1,'"],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ma.optgroup=ma.option;ma.tbody=ma.tfoot=ma.colgroup=ma.caption=ma.thead;ma.th=ma.td;var Oa=R.prototype={ready:function(b){function a(){c||(c= +!0,b())}var c=!1;"complete"===W.readyState?setTimeout(a):(this.on("DOMContentLoaded",a),R(N).on("load",a))},toString:function(){var b=[];n(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return 0<=b?z(this[b]):z(this[this.length+b])},length:0,push:jg,sort:[].sort,splice:[].splice},zb={};n("multiple selected checked disabled readOnly required open".split(" "),function(b){zb[E(b)]=b});var Sc={};n("input select option textarea button form details".split(" "),function(b){Sc[b]= +!0});var Tc={ngMinlength:"minlength",ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",ngPattern:"pattern"};n({data:Wb,removeData:sb},function(b,a){R[a]=b});n({data:Wb,inheritedData:yb,scope:function(b){return z.data(b,"$scope")||yb(b.parentNode||b,["$isolateScope","$scope"])},isolateScope:function(b){return z.data(b,"$isolateScope")||z.data(b,"$isolateScopeNoTemplate")},controller:Pc,injector:function(b){return yb(b,"$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:vb,css:function(b, +a,c){a=eb(a);if(y(c))b.style[a]=c;else return b.style[a]},attr:function(b,a,c){var d=b.nodeType;if(d!==ab&&2!==d&&8!==d)if(d=E(a),zb[d])if(y(c))c?(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||w).specified?d:u;else if(y(c))b.setAttribute(a,c);else if(b.getAttribute)return b=b.getAttribute(a,2),null===b?u:b},prop:function(b,a,c){if(y(c))b[a]=c;else return b[a]},text:function(){function b(a,b){if(v(b)){var d=a.nodeType;return d===pa||d=== +ab?a.textContent:""}a.textContent=b}b.$dv="";return b}(),val:function(b,a){if(v(a)){if(b.multiple&&"select"===ta(b)){var c=[];n(b.options,function(a){a.selected&&c.push(a.value||a.text)});return 0===c.length?null:c}return b.value}b.value=a},html:function(b,a){if(v(a))return b.innerHTML;rb(b,!0);b.innerHTML=a},empty:Qc},function(b,a){R.prototype[a]=function(a,d){var e,f,g=this.length;if(b!==Qc&&(2==b.length&&b!==vb&&b!==Pc?a:d)===u){if(C(a)){for(e=0;e <= >= && || ! = |".split(" "),function(a){Mb[a]=!0});var pg={n:"\n",f:"\f",r:"\r",t:"\t",v:"\v","'":"'",'"':'"'},gc=function(a){this.options=a};gc.prototype={constructor:gc,lex:function(a){this.text=a;this.index= +0;for(this.tokens=[];this.index=a&&"string"===typeof a},isWhitespace:function(a){return" "===a||"\r"===a||"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdent:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isExpOperator:function(a){return"-"=== +a||"+"===a||this.isNumber(a)},throwError:function(a,c,d){d=d||this.index;c=y(c)?"s "+c+"-"+this.index+" ["+this.text.substring(c,d)+"]":" "+d;throw ca("lexerr",a,c,this.text);},readNumber:function(){for(var a="",c=this.index;this.index","<=",">=");)a={type:q.BinaryExpression,operator:c.text, +left:a,right:this.additive()};return a},additive:function(){for(var a=this.multiplicative(),c;c=this.expect("+","-");)a={type:q.BinaryExpression,operator:c.text,left:a,right:this.multiplicative()};return a},multiplicative:function(){for(var a=this.unary(),c;c=this.expect("*","/","%");)a={type:q.BinaryExpression,operator:c.text,left:a,right:this.unary()};return a},unary:function(){var a;return(a=this.expect("+","-","!"))?{type:q.UnaryExpression,operator:a.text,prefix:!0,argument:this.unary()}:this.primary()}, +primary:function(){var a;this.expect("(")?(a=this.filterChain(),this.consume(")")):this.expect("[")?a=this.arrayDeclaration():this.expect("{")?a=this.object():this.constants.hasOwnProperty(this.peek().text)?a=ua(this.constants[this.consume().text]):this.peek().identifier?a=this.identifier():this.peek().constant?a=this.constant():this.throwError("not a primary expression",this.peek());for(var c;c=this.expect("(","[",".");)"("===c.text?(a={type:q.CallExpression,callee:a,arguments:this.parseArguments()}, +this.consume(")")):"["===c.text?(a={type:q.MemberExpression,object:a,property:this.expression(),computed:!0},this.consume("]")):"."===c.text?a={type:q.MemberExpression,object:a,property:this.identifier(),computed:!1}:this.throwError("IMPOSSIBLE");return a},filter:function(a){a=[a];for(var c={type:q.CallExpression,callee:this.identifier(),arguments:a,filter:!0};this.expect(":");)a.push(this.expression());return c},parseArguments:function(){var a=[];if(")"!==this.peekToken().text){do a.push(this.expression()); +while(this.expect(","))}return a},identifier:function(){var a=this.consume();a.identifier||this.throwError("is not a valid identifier",a);return{type:q.Identifier,name:a.text}},constant:function(){return{type:q.Literal,value:this.consume().value}},arrayDeclaration:function(){var a=[];if("]"!==this.peekToken().text){do{if(this.peek("]"))break;a.push(this.expression())}while(this.expect(","))}this.consume("]");return{type:q.ArrayExpression,elements:a}},object:function(){var a=[],c;if("}"!==this.peekToken().text){do{if(this.peek("}"))break; +c={type:q.Property,kind:"init"};this.peek().constant?c.key=this.constant():this.peek().identifier?c.key=this.identifier():this.throwError("invalid key",this.peek());this.consume(":");c.value=this.expression();a.push(c)}while(this.expect(","))}this.consume("}");return{type:q.ObjectExpression,properties:a}},throwError:function(a,c){throw ca("syntax",c.text,a,c.index+1,this.text,this.text.substring(c.index));},consume:function(a){if(0===this.tokens.length)throw ca("ueoe",this.text);var c=this.expect(a); +c||this.throwError("is unexpected, expecting ["+a+"]",this.peek());return c},peekToken:function(){if(0===this.tokens.length)throw ca("ueoe",this.text);return this.tokens[0]},peek:function(a,c,d,e){return this.peekAhead(0,a,c,d,e)},peekAhead:function(a,c,d,e,f){if(this.tokens.length>a){a=this.tokens[a];var g=a.text;if(g===c||g===d||g===e||g===f||!(c||d||e||f))return a}return!1},expect:function(a,c,d,e){return(a=this.peek(a,c,d,e))?(this.tokens.shift(),a):!1},constants:{"true":{type:q.Literal,value:!0}, +"false":{type:q.Literal,value:!1},"null":{type:q.Literal,value:null},undefined:{type:q.Literal,value:u},"this":{type:q.ThisExpression}}};qd.prototype={compile:function(a,c){var d=this,e=this.astBuilder.ast(a);this.state={nextId:0,filters:{},expensiveChecks:c,fn:{vars:[],body:[],own:{}},assign:{vars:[],body:[],own:{}},inputs:[]};U(e,d.$filter);var f="",g;this.stage="assign";if(g=od(e))this.state.computing="assign",f=this.nextId(),this.recurse(g,f),f="fn.assign="+this.generateFunction("assign","s,v,l"); +g=md(e.body);d.stage="inputs";n(g,function(a,c){var e="fn"+c;d.state[e]={vars:[],body:[],own:{}};d.state.computing=e;var f=d.nextId();d.recurse(a,f);d.return_(f);d.state.inputs.push(e);a.watchId=c});this.state.computing="fn";this.stage="main";this.recurse(e);f='"'+this.USE+" "+this.STRICT+'";\n'+this.filterPrefix()+"var fn="+this.generateFunction("fn","s,l,a,i")+f+this.watchFns()+"return fn;";f=(new Function("$filter","ensureSafeMemberName","ensureSafeObject","ensureSafeFunction","ifDefined","plus", +"text",f))(this.$filter,Ba,na,kd,Wf,ld,a);this.state=this.stage=u;f.literal=pd(e);f.constant=e.constant;return f},USE:"use",STRICT:"strict",watchFns:function(){var a=[],c=this.state.inputs,d=this;n(c,function(c){a.push("var "+c+"="+d.generateFunction(c,"s"))});c.length&&a.push("fn.inputs=["+c.join(",")+"];");return a.join("")},generateFunction:function(a,c){return"function("+c+"){"+this.varsPrefix(a)+this.body(a)+"};"},filterPrefix:function(){var a=[],c=this;n(this.state.filters,function(d,e){a.push(d+ +"=$filter("+c.escape(e)+")")});return a.length?"var "+a.join(",")+";":""},varsPrefix:function(a){return this.state[a].vars.length?"var "+this.state[a].vars.join(",")+";":""},body:function(a){return this.state[a].body.join("")},recurse:function(a,c,d,e,f,g){var h,l,k=this,m,r;e=e||w;if(!g&&y(a.watchId))c=c||this.nextId(),this.if_("i",this.lazyAssign(c,this.computedMember("i",a.watchId)),this.lazyRecurse(a,c,d,e,f,!0));else switch(a.type){case q.Program:n(a.body,function(c,d){k.recurse(c.expression, +u,u,function(a){l=a});d!==a.body.length-1?k.current().body.push(l,";"):k.return_(l)});break;case q.Literal:r=this.escape(a.value);this.assign(c,r);e(r);break;case q.UnaryExpression:this.recurse(a.argument,u,u,function(a){l=a});r=a.operator+"("+this.ifDefined(l,0)+")";this.assign(c,r);e(r);break;case q.BinaryExpression:this.recurse(a.left,u,u,function(a){h=a});this.recurse(a.right,u,u,function(a){l=a});r="+"===a.operator?this.plus(h,l):"-"===a.operator?this.ifDefined(h,0)+a.operator+this.ifDefined(l, +0):"("+h+")"+a.operator+"("+l+")";this.assign(c,r);e(r);break;case q.LogicalExpression:c=c||this.nextId();k.recurse(a.left,c);k.if_("&&"===a.operator?c:k.not(c),k.lazyRecurse(a.right,c));e(c);break;case q.ConditionalExpression:c=c||this.nextId();k.recurse(a.test,c);k.if_(c,k.lazyRecurse(a.alternate,c),k.lazyRecurse(a.consequent,c));e(c);break;case q.Identifier:c=c||this.nextId();d&&(d.context="inputs"===k.stage?"s":this.assign(this.nextId(),this.getHasOwnProperty("l",a.name)+"?l:s"),d.computed=!1, +d.name=a.name);Ba(a.name);k.if_("inputs"===k.stage||k.not(k.getHasOwnProperty("l",a.name)),function(){k.if_("inputs"===k.stage||"s",function(){f&&1!==f&&k.if_(k.not(k.nonComputedMember("s",a.name)),k.lazyAssign(k.nonComputedMember("s",a.name),"{}"));k.assign(c,k.nonComputedMember("s",a.name))})},c&&k.lazyAssign(c,k.nonComputedMember("l",a.name)));(k.state.expensiveChecks||Fb(a.name))&&k.addEnsureSafeObject(c);e(c);break;case q.MemberExpression:h=d&&(d.context=this.nextId())||this.nextId();c=c||this.nextId(); +k.recurse(a.object,h,u,function(){k.if_(k.notNull(h),function(){if(a.computed)l=k.nextId(),k.recurse(a.property,l),k.addEnsureSafeMemberName(l),f&&1!==f&&k.if_(k.not(k.computedMember(h,l)),k.lazyAssign(k.computedMember(h,l),"{}")),r=k.ensureSafeObject(k.computedMember(h,l)),k.assign(c,r),d&&(d.computed=!0,d.name=l);else{Ba(a.property.name);f&&1!==f&&k.if_(k.not(k.nonComputedMember(h,a.property.name)),k.lazyAssign(k.nonComputedMember(h,a.property.name),"{}"));r=k.nonComputedMember(h,a.property.name); +if(k.state.expensiveChecks||Fb(a.property.name))r=k.ensureSafeObject(r);k.assign(c,r);d&&(d.computed=!1,d.name=a.property.name)}e(c)})},!!f);break;case q.CallExpression:c=c||this.nextId();a.filter?(l=k.filter(a.callee.name),m=[],n(a.arguments,function(a){var c=k.nextId();k.recurse(a,c);m.push(c)}),r=l+"("+m.join(",")+")",k.assign(c,r),e(c)):(l=k.nextId(),h={},m=[],k.recurse(a.callee,l,h,function(){k.if_(k.notNull(l),function(){k.addEnsureSafeFunction(l);n(a.arguments,function(a){k.recurse(a,k.nextId(), +u,function(a){m.push(k.ensureSafeObject(a))})});h.name?(k.state.expensiveChecks||k.addEnsureSafeObject(h.context),r=k.member(h.context,h.name,h.computed)+"("+m.join(",")+")"):r=l+"("+m.join(",")+")";r=k.ensureSafeObject(r);k.assign(c,r);e(c)})}));break;case q.AssignmentExpression:l=this.nextId();h={};if(!nd(a.left))throw ca("lval");this.recurse(a.left,u,h,function(){k.if_(k.notNull(h.context),function(){k.recurse(a.right,l);k.addEnsureSafeObject(k.member(h.context,h.name,h.computed));r=k.member(h.context, +h.name,h.computed)+a.operator+l;k.assign(c,r);e(c||r)})},1);break;case q.ArrayExpression:m=[];n(a.elements,function(a){k.recurse(a,k.nextId(),u,function(a){m.push(a)})});r="["+m.join(",")+"]";this.assign(c,r);e(r);break;case q.ObjectExpression:m=[];n(a.properties,function(a){k.recurse(a.value,k.nextId(),u,function(c){m.push(k.escape(a.key.type===q.Identifier?a.key.name:""+a.key.value)+":"+c)})});r="{"+m.join(",")+"}";this.assign(c,r);e(r);break;case q.ThisExpression:this.assign(c,"s");e("s");break; +case q.NGValueParameter:this.assign(c,"v"),e("v")}},getHasOwnProperty:function(a,c){var d=a+"."+c,e=this.current().own;e.hasOwnProperty(d)||(e[d]=this.nextId(!1,a+"&&("+this.escape(c)+" in "+a+")"));return e[d]},assign:function(a,c){if(a)return this.current().body.push(a,"=",c,";"),a},filter:function(a){this.state.filters.hasOwnProperty(a)||(this.state.filters[a]=this.nextId(!0));return this.state.filters[a]},ifDefined:function(a,c){return"ifDefined("+a+","+this.escape(c)+")"},plus:function(a,c){return"plus("+ +a+","+c+")"},return_:function(a){this.current().body.push("return ",a,";")},if_:function(a,c,d){if(!0===a)c();else{var e=this.current().body;e.push("if(",a,"){");c();e.push("}");d&&(e.push("else{"),d(),e.push("}"))}},not:function(a){return"!("+a+")"},notNull:function(a){return a+"!=null"},nonComputedMember:function(a,c){return a+"."+c},computedMember:function(a,c){return a+"["+c+"]"},member:function(a,c,d){return d?this.computedMember(a,c):this.nonComputedMember(a,c)},addEnsureSafeObject:function(a){this.current().body.push(this.ensureSafeObject(a), +";")},addEnsureSafeMemberName:function(a){this.current().body.push(this.ensureSafeMemberName(a),";")},addEnsureSafeFunction:function(a){this.current().body.push(this.ensureSafeFunction(a),";")},ensureSafeObject:function(a){return"ensureSafeObject("+a+",text)"},ensureSafeMemberName:function(a){return"ensureSafeMemberName("+a+",text)"},ensureSafeFunction:function(a){return"ensureSafeFunction("+a+",text)"},lazyRecurse:function(a,c,d,e,f,g){var h=this;return function(){h.recurse(a,c,d,e,f,g)}},lazyAssign:function(a, +c){var d=this;return function(){d.assign(a,c)}},stringEscapeRegex:/[^ a-zA-Z0-9]/g,stringEscapeFn:function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)},escape:function(a){if(L(a))return"'"+a.replace(this.stringEscapeRegex,this.stringEscapeFn)+"'";if(V(a))return a.toString();if(!0===a)return"true";if(!1===a)return"false";if(null===a)return"null";if("undefined"===typeof a)return"undefined";throw ca("esc");},nextId:function(a,c){var d="v"+this.state.nextId++;a||this.current().vars.push(d+ +(c?"="+c:""));return d},current:function(){return this.state[this.state.computing]}};rd.prototype={compile:function(a,c){var d=this,e=this.astBuilder.ast(a);this.expression=a;this.expensiveChecks=c;U(e,d.$filter);var f,g;if(f=od(e))g=this.recurse(f);f=md(e.body);var h;f&&(h=[],n(f,function(a,c){var e=d.recurse(a);a.input=e;h.push(e);a.watchId=c}));var l=[];n(e.body,function(a){l.push(d.recurse(a.expression))});f=0===e.body.length?function(){}:1===e.body.length?l[0]:function(a,c){var d;n(l,function(e){d= +e(a,c)});return d};g&&(f.assign=function(a,c,d){return g(a,d,c)});h&&(f.inputs=h);f.literal=pd(e);f.constant=e.constant;return f},recurse:function(a,c,d){var e,f,g=this,h;if(a.input)return this.inputs(a.input,a.watchId);switch(a.type){case q.Literal:return this.value(a.value,c);case q.UnaryExpression:return f=this.recurse(a.argument),this["unary"+a.operator](f,c);case q.BinaryExpression:return e=this.recurse(a.left),f=this.recurse(a.right),this["binary"+a.operator](e,f,c);case q.LogicalExpression:return e= +this.recurse(a.left),f=this.recurse(a.right),this["binary"+a.operator](e,f,c);case q.ConditionalExpression:return this["ternary?:"](this.recurse(a.test),this.recurse(a.alternate),this.recurse(a.consequent),c);case q.Identifier:return Ba(a.name,g.expression),g.identifier(a.name,g.expensiveChecks||Fb(a.name),c,d,g.expression);case q.MemberExpression:return e=this.recurse(a.object,!1,!!d),a.computed||(Ba(a.property.name,g.expression),f=a.property.name),a.computed&&(f=this.recurse(a.property)),a.computed? +this.computedMember(e,f,c,d,g.expression):this.nonComputedMember(e,f,g.expensiveChecks,c,d,g.expression);case q.CallExpression:return h=[],n(a.arguments,function(a){h.push(g.recurse(a))}),a.filter&&(f=this.$filter(a.callee.name)),a.filter||(f=this.recurse(a.callee,!0)),a.filter?function(a,d,e,g){for(var n=[],q=0;q":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)>c(e,f,g,h);return d?{value:e}:e}},"binary<=":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)<=c(e,f,g,h);return d?{value:e}:e}},"binary>=":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)>=c(e,f,g,h);return d?{value:e}: +e}},"binary&&":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)&&c(e,f,g,h);return d?{value:e}:e}},"binary||":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)||c(e,f,g,h);return d?{value:e}:e}},"ternary?:":function(a,c,d,e){return function(f,g,h,l){f=a(f,g,h,l)?c(f,g,h,l):d(f,g,h,l);return e?{value:f}:f}},value:function(a,c){return function(){return c?{context:u,name:u,value:a}:a}},identifier:function(a,c,d,e,f){return function(g,h,l,k){g=h&&a in h?h:g;e&&1!==e&&g&&!g[a]&&(g[a]={});h=g? +g[a]:u;c&&na(h,f);return d?{context:g,name:a,value:h}:h}},computedMember:function(a,c,d,e,f){return function(g,h,l,k){var m=a(g,h,l,k),n,s;null!=m&&(n=c(g,h,l,k),Ba(n,f),e&&1!==e&&m&&!m[n]&&(m[n]={}),s=m[n],na(s,f));return d?{context:m,name:n,value:s}:s}},nonComputedMember:function(a,c,d,e,f,g){return function(h,l,k,m){h=a(h,l,k,m);f&&1!==f&&h&&!h[c]&&(h[c]={});l=null!=h?h[c]:u;(d||Fb(c))&&na(l,g);return e?{context:h,name:c,value:l}:l}},inputs:function(a,c){return function(d,e,f,g){return g?g[c]: +a(d,e,f)}}};var hc=function(a,c,d){this.lexer=a;this.$filter=c;this.options=d;this.ast=new q(this.lexer);this.astCompiler=d.csp?new rd(this.ast,c):new qd(this.ast,c)};hc.prototype={constructor:hc,parse:function(a){return this.astCompiler.compile(a,this.options.expensiveChecks)}};ga();ga();var Xf=Object.prototype.valueOf,Ca=F("$sce"),oa={HTML:"html",CSS:"css",URL:"url",RESOURCE_URL:"resourceUrl",JS:"js"},ea=F("$compile"),Z=W.createElement("a"),vd=Aa(N.location.href);wd.$inject=["$document"];Kc.$inject= +["$provide"];xd.$inject=["$locale"];zd.$inject=["$locale"];var Cd=".",gg={yyyy:$("FullYear",4),yy:$("FullYear",2,0,!0),y:$("FullYear",1),MMMM:Hb("Month"),MMM:Hb("Month",!0),MM:$("Month",2,1),M:$("Month",1,1),dd:$("Date",2),d:$("Date",1),HH:$("Hours",2),H:$("Hours",1),hh:$("Hours",2,-12),h:$("Hours",1,-12),mm:$("Minutes",2),m:$("Minutes",1),ss:$("Seconds",2),s:$("Seconds",1),sss:$("Milliseconds",3),EEEE:Hb("Day"),EEE:Hb("Day",!0),a:function(a,c){return 12>a.getHours()?c.AMPMS[0]:c.AMPMS[1]},Z:function(a, +c,d){a=-1*d;return a=(0<=a?"+":"")+(Gb(Math[0=a.getFullYear()?c.ERANAMES[0]:c.ERANAMES[1]}},fg=/((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,eg=/^\-?\d+$/;yd.$inject=["$locale"];var bg=qa(E),cg=qa(pb);Ad.$inject=["$parse"];var he=qa({restrict:"E",compile:function(a,c){if(!c.href&&!c.xlinkHref)return function(a,c){if("a"===c[0].nodeName.toLowerCase()){var f= +"[object SVGAnimatedString]"===sa.call(c.prop("href"))?"xlink:href":"href";c.on("click",function(a){c.attr(f)||a.preventDefault()})}}}}),qb={};n(zb,function(a,c){function d(a,d,f){a.$watch(f[e],function(a){f.$set(c,!!a)})}if("multiple"!=a){var e=xa("ng-"+c),f=d;"checked"===a&&(f=function(a,c,f){f.ngModel!==f[e]&&d(a,c,f)});qb[e]=function(){return{restrict:"A",priority:100,link:f}}}});n(Tc,function(a,c){qb[c]=function(){return{priority:100,link:function(a,e,f){if("ngPattern"===c&&"/"==f.ngPattern.charAt(0)&& +(e=f.ngPattern.match(ig))){f.$set("ngPattern",new RegExp(e[1],e[2]));return}a.$watch(f[c],function(a){f.$set(c,a)})}}}});n(["src","srcset","href"],function(a){var c=xa("ng-"+a);qb[c]=function(){return{priority:99,link:function(d,e,f){var g=a,h=a;"href"===a&&"[object SVGAnimatedString]"===sa.call(e.prop("href"))&&(h="xlinkHref",f.$attr[h]="xlink:href",g=null);f.$observe(c,function(c){c?(f.$set(h,c),gb&&g&&e.prop(g,f[h])):"href"===a&&f.$set(h,null)})}}}});var Ib={$addControl:w,$$renameControl:function(a, +c){a.$name=c},$removeControl:w,$setValidity:w,$setDirty:w,$setPristine:w,$setSubmitted:w};Fd.$inject=["$element","$attrs","$scope","$animate","$interpolate"];var Nd=function(a){return["$timeout",function(c){return{name:"form",restrict:a?"EAC":"E",controller:Fd,compile:function(d,e){d.addClass(Sa).addClass(jb);var f=e.name?"name":a&&e.ngForm?"ngForm":!1;return{pre:function(a,d,e,k){if(!("action"in e)){var m=function(c){a.$apply(function(){k.$commitViewValue();k.$setSubmitted()});c.preventDefault()}; +d[0].addEventListener("submit",m,!1);d.on("$destroy",function(){c(function(){d[0].removeEventListener("submit",m,!1)},0,!1)})}var n=k.$$parentForm;f&&(Eb(a,k.$name,k,k.$name),e.$observe(f,function(c){k.$name!==c&&(Eb(a,k.$name,u,k.$name),n.$$renameControl(k,c),Eb(a,k.$name,k,k.$name))}));d.on("$destroy",function(){n.$removeControl(k);f&&Eb(a,e[f],u,k.$name);Q(k,Ib)})}}}}}]},ie=Nd(),ve=Nd(!0),hg=/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/,qg=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/, +rg=/^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,sg=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/,Od=/^(\d{4})-(\d{2})-(\d{2})$/,Pd=/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,mc=/^(\d{4})-W(\d\d)$/,Qd=/^(\d{4})-(\d\d)$/,Rd=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Sd={text:function(a,c,d,e,f,g){hb(a,c,d,e,f,g);kc(e)},date:ib("date",Od,Kb(Od,["yyyy","MM","dd"]),"yyyy-MM-dd"),"datetime-local":ib("datetimelocal",Pd,Kb(Pd,"yyyy MM dd HH mm ss sss".split(" ")), +"yyyy-MM-ddTHH:mm:ss.sss"),time:ib("time",Rd,Kb(Rd,["HH","mm","ss","sss"]),"HH:mm:ss.sss"),week:ib("week",mc,function(a,c){if(da(a))return a;if(L(a)){mc.lastIndex=0;var d=mc.exec(a);if(d){var e=+d[1],f=+d[2],g=d=0,h=0,l=0,k=Dd(e),f=7*(f-1);c&&(d=c.getHours(),g=c.getMinutes(),h=c.getSeconds(),l=c.getMilliseconds());return new Date(e,0,k.getDate()+f,d,g,h,l)}}return NaN},"yyyy-Www"),month:ib("month",Qd,Kb(Qd,["yyyy","MM"]),"yyyy-MM"),number:function(a,c,d,e,f,g){Hd(a,c,d,e);hb(a,c,d,e,f,g);e.$$parserName= +"number";e.$parsers.push(function(a){return e.$isEmpty(a)?null:sg.test(a)?parseFloat(a):u});e.$formatters.push(function(a){if(!e.$isEmpty(a)){if(!V(a))throw Lb("numfmt",a);a=a.toString()}return a});if(y(d.min)||d.ngMin){var h;e.$validators.min=function(a){return e.$isEmpty(a)||v(h)||a>=h};d.$observe("min",function(a){y(a)&&!V(a)&&(a=parseFloat(a,10));h=V(a)&&!isNaN(a)?a:u;e.$validate()})}if(y(d.max)||d.ngMax){var l;e.$validators.max=function(a){return e.$isEmpty(a)||v(l)||a<=l};d.$observe("max",function(a){y(a)&& +!V(a)&&(a=parseFloat(a,10));l=V(a)&&!isNaN(a)?a:u;e.$validate()})}},url:function(a,c,d,e,f,g){hb(a,c,d,e,f,g);kc(e);e.$$parserName="url";e.$validators.url=function(a,c){var d=a||c;return e.$isEmpty(d)||qg.test(d)}},email:function(a,c,d,e,f,g){hb(a,c,d,e,f,g);kc(e);e.$$parserName="email";e.$validators.email=function(a,c){var d=a||c;return e.$isEmpty(d)||rg.test(d)}},radio:function(a,c,d,e){v(d.name)&&c.attr("name",++lb);c.on("click",function(a){c[0].checked&&e.$setViewValue(d.value,a&&a.type)});e.$render= +function(){c[0].checked=d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a,c,d,e,f,g,h,l){var k=Id(l,a,"ngTrueValue",d.ngTrueValue,!0),m=Id(l,a,"ngFalseValue",d.ngFalseValue,!1);c.on("click",function(a){e.$setViewValue(c[0].checked,a&&a.type)});e.$render=function(){c[0].checked=e.$viewValue};e.$isEmpty=function(a){return!1===a};e.$formatters.push(function(a){return ka(a,k)});e.$parsers.push(function(a){return a?k:m})},hidden:w,button:w,submit:w,reset:w,file:w},Ec=["$browser", +"$sniffer","$filter","$parse",function(a,c,d,e){return{restrict:"E",require:["?ngModel"],link:{pre:function(f,g,h,l){l[0]&&(Sd[E(h.type)]||Sd.text)(f,g,h,l[0],c,a,d,e)}}}}],tg=/^(true|false|\d+)$/,Ne=function(){return{restrict:"A",priority:100,compile:function(a,c){return tg.test(c.ngValue)?function(a,c,f){f.$set("value",a.$eval(f.ngValue))}:function(a,c,f){a.$watch(f.ngValue,function(a){f.$set("value",a)})}}}},ne=["$compile",function(a){return{restrict:"AC",compile:function(c){a.$$addBindingClass(c); +return function(c,e,f){a.$$addBindingInfo(e,f.ngBind);e=e[0];c.$watch(f.ngBind,function(a){e.textContent=a===u?"":a})}}}}],pe=["$interpolate","$compile",function(a,c){return{compile:function(d){c.$$addBindingClass(d);return function(d,f,g){d=a(f.attr(g.$attr.ngBindTemplate));c.$$addBindingInfo(f,d.expressions);f=f[0];g.$observe("ngBindTemplate",function(a){f.textContent=a===u?"":a})}}}}],oe=["$sce","$parse","$compile",function(a,c,d){return{restrict:"A",compile:function(e,f){var g=c(f.ngBindHtml), +h=c(f.ngBindHtml,function(a){return(a||"").toString()});d.$$addBindingClass(e);return function(c,e,f){d.$$addBindingInfo(e,f.ngBindHtml);c.$watch(h,function(){e.html(a.getTrustedHtml(g(c))||"")})}}}}],Me=qa({restrict:"A",require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),qe=lc("",!0),se=lc("Odd",0),re=lc("Even",1),te=Ma({compile:function(a,c){c.$set("ngCloak",u);a.removeClass("ng-cloak")}}),ue=[function(){return{restrict:"A",scope:!0,controller:"@", +priority:500}}],Jc={},ug={blur:!0,focus:!0};n("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),function(a){var c=xa("ng-"+a);Jc[c]=["$parse","$rootScope",function(d,e){return{restrict:"A",compile:function(f,g){var h=d(g[c],null,!0);return function(c,d){d.on(a,function(d){var f=function(){h(c,{$event:d})};ug[a]&&e.$$phase?c.$evalAsync(f):c.$apply(f)})}}}}]});var xe=["$animate",function(a){return{multiElement:!0, +transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(c,d,e,f,g){var h,l,k;c.$watch(e.ngIf,function(c){c?l||g(function(c,f){l=f;c[c.length++]=W.createComment(" end ngIf: "+e.ngIf+" ");h={clone:c};a.enter(c,d.parent(),d)}):(k&&(k.remove(),k=null),l&&(l.$destroy(),l=null),h&&(k=ob(h.clone),a.leave(k).then(function(){k=null}),h=null))})}}}],ye=["$templateRequest","$anchorScroll","$animate","$sce",function(a,c,d,e){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element", +controller:aa.noop,compile:function(f,g){var h=g.ngInclude||g.src,l=g.onload||"",k=g.autoscroll;return function(f,g,n,q,u){var v=0,t,p,x,w=function(){p&&(p.remove(),p=null);t&&(t.$destroy(),t=null);x&&(d.leave(x).then(function(){p=null}),p=x,x=null)};f.$watch(e.parseAsResourceUrl(h),function(e){var h=function(){!y(k)||k&&!f.$eval(k)||c()},n=++v;e?(a(e,!0).then(function(a){if(n===v){var c=f.$new();q.template=a;a=u(c,function(a){w();d.enter(a,null,g).then(h)});t=c;x=a;t.$emit("$includeContentLoaded", +e);f.$eval(l)}},function(){n===v&&(w(),f.$emit("$includeContentError",e))}),f.$emit("$includeContentRequested",e)):(w(),q.template=null)})}}}}],Pe=["$compile",function(a){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(c,d,e,f){/SVG/.test(d[0].toString())?(d.empty(),a(Mc(f.template,W).childNodes)(c,function(a){d.append(a)},{futureParentElement:d})):(d.html(f.template),a(d.contents())(c))}}}],ze=Ma({priority:450,compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}), +Le=function(){return{restrict:"A",priority:100,require:"ngModel",link:function(a,c,d,e){var f=c.attr(d.$attr.ngList)||", ",g="false"!==d.ngTrim,h=g?T(f):f;e.$parsers.push(function(a){if(!v(a)){var c=[];a&&n(a.split(h),function(a){a&&c.push(g?T(a):a)});return c}});e.$formatters.push(function(a){return K(a)?a.join(f):u});e.$isEmpty=function(a){return!a||!a.length}}}},jb="ng-valid",Jd="ng-invalid",Sa="ng-pristine",Jb="ng-dirty",Ld="ng-pending",Lb=new F("ngModel"),vg=["$scope","$exceptionHandler","$attrs", +"$element","$parse","$animate","$timeout","$rootScope","$q","$interpolate",function(a,c,d,e,f,g,h,l,k,m){this.$modelValue=this.$viewValue=Number.NaN;this.$$rawModelValue=u;this.$validators={};this.$asyncValidators={};this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$untouched=!0;this.$touched=!1;this.$pristine=!0;this.$dirty=!1;this.$valid=!0;this.$invalid=!1;this.$error={};this.$$success={};this.$pending=u;this.$name=m(d.name||"",!1)(a);var r=f(d.ngModel),s=r.assign,q=r,H=s, +M=null,t,p=this;this.$$setOptions=function(a){if((p.$options=a)&&a.getterSetter){var c=f(d.ngModel+"()"),g=f(d.ngModel+"($$$p)");q=function(a){var d=r(a);G(d)&&(d=c(a));return d};H=function(a,c){G(r(a))?g(a,{$$$p:p.$modelValue}):s(a,p.$modelValue)}}else if(!r.assign)throw Lb("nonassign",d.ngModel,va(e));};this.$render=w;this.$isEmpty=function(a){return v(a)||""===a||null===a||a!==a};var x=e.inheritedData("$formController")||Ib,z=0;Gd({ctrl:this,$element:e,set:function(a,c){a[c]=!0},unset:function(a, +c){delete a[c]},parentForm:x,$animate:g});this.$setPristine=function(){p.$dirty=!1;p.$pristine=!0;g.removeClass(e,Jb);g.addClass(e,Sa)};this.$setDirty=function(){p.$dirty=!0;p.$pristine=!1;g.removeClass(e,Sa);g.addClass(e,Jb);x.$setDirty()};this.$setUntouched=function(){p.$touched=!1;p.$untouched=!0;g.setClass(e,"ng-untouched","ng-touched")};this.$setTouched=function(){p.$touched=!0;p.$untouched=!1;g.setClass(e,"ng-touched","ng-untouched")};this.$rollbackViewValue=function(){h.cancel(M);p.$viewValue= +p.$$lastCommittedViewValue;p.$render()};this.$validate=function(){if(!V(p.$modelValue)||!isNaN(p.$modelValue)){var a=p.$$rawModelValue,c=p.$valid,d=p.$modelValue,e=p.$options&&p.$options.allowInvalid;p.$$runValidators(a,p.$$lastCommittedViewValue,function(f){e||c===f||(p.$modelValue=f?a:u,p.$modelValue!==d&&p.$$writeModelToScope())})}};this.$$runValidators=function(a,c,d){function e(){var d=!0;n(p.$validators,function(e,f){var h=e(a,c);d=d&&h;g(f,h)});return d?!0:(n(p.$asyncValidators,function(a, +c){g(c,null)}),!1)}function f(){var d=[],e=!0;n(p.$asyncValidators,function(f,h){var k=f(a,c);if(!k||!G(k.then))throw Lb("$asyncValidators",k);g(h,u);d.push(k.then(function(){g(h,!0)},function(a){e=!1;g(h,!1)}))});d.length?k.all(d).then(function(){h(e)},w):h(!0)}function g(a,c){l===z&&p.$setValidity(a,c)}function h(a){l===z&&d(a)}z++;var l=z;(function(){var a=p.$$parserName||"parse";if(t===u)g(a,null);else return t||(n(p.$validators,function(a,c){g(c,null)}),n(p.$asyncValidators,function(a,c){g(c, +null)})),g(a,t),t;return!0})()?e()?f():h(!1):h(!1)};this.$commitViewValue=function(){var a=p.$viewValue;h.cancel(M);if(p.$$lastCommittedViewValue!==a||""===a&&p.$$hasNativeValidators)p.$$lastCommittedViewValue=a,p.$pristine&&this.$setDirty(),this.$$parseAndValidate()};this.$$parseAndValidate=function(){var c=p.$$lastCommittedViewValue;if(t=v(c)?u:!0)for(var d=0;df||e.$isEmpty(c)||c.length<=f}}}}},Hc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f=0;d.$observe("minlength",function(a){f=Y(a)||0;e.$validate()});e.$validators.minlength=function(a, +c){return e.$isEmpty(c)||c.length>=f}}}}};N.angular.bootstrap?console.log("WARNING: Tried to load angular more than once."):(be(),de(aa),z(W).ready(function(){Yd(W,zc)}))})(window,document);!window.angular.$$csp()&&window.angular.element(document).find("head").prepend(''); +//# sourceMappingURL=angular.min.js.map diff --git a/routes/backend.js b/routes/backend.js new file mode 100755 index 0000000..2b8d950 --- /dev/null +++ b/routes/backend.js @@ -0,0 +1,134 @@ +var Types = require('Joi'); +var _ = require('lodash'); + +module.exports = function(server) { + server.route({ + method: 'GET', + path: '/runners', + handler: function (request, reply) { + if (request.query.bid) { + server.methods.getRunnerByID(request.query.bid, function(err, runner) { + if (err) { + console.log(err); + } else { + reply(runner).code(200); + } + }); + } else { + server.methods.getRunners( function(err, runners) { + if (err) { + console.log(err); + } else { + reply(runners).code(200); + } + }); + } + }, + config: { + validate: { + query: { + bid: Types.string() + } + } + } + + }); + + server.route({ + method: 'POST', + path: '/runners', + handler: function (request, reply) { + var runner = { + bid: request.payload.bid, + name: request.payload.name, + start_time:request.payload.team, + team:request.payload.team + }; + server.methods.addRunner(runner, function(err, newRunner) { + if (err) { + console.log(err); + } else { + reply(newRunner).code(200); + } + }); + }, + config: { + validate: { + payload: { + bid: Types.string().required().min(3), + name: Types.string().required().min(3), + start_time: Types.date(), + team: Types.string() + } + } + } + }); + + server.route({ + method: 'GET', + path: '/laps', + handler: function (request, reply) { + if (request.query.bid) { + server.methods.getLapsByID(request.query.bid, function(err, laps) { + if (err) { + console.log(err); + } else { + + reply(laps).code(200); + } + }); + } else { + server.methods.getLaps( function(err, laps) { + if (err) { + console.log(err); + } else { + reply(laps).code(200); + } + }); + } + }, + config: { + validate: { + query: { + bid: Types.string() + } + } + } + }); + + server.route({ + method: 'POST', + path: '/laps', + handler: function (request, reply) { + var lap = { + bid: request.payload.bid, + time: new Date() + }; + server.methods.logLap(lap); + server.methods.addLap(lap, function(err, newLap) { + if (err) { + console.log(err); + } else { + reply(newLap).code(200); + } + }); + }, + config: { + validate: { + payload: { + bid: Types.string().required().min(3) + } + } + } + }); + + server.route({ + method: 'GET', + path: '/top', + handler: function (request, reply) { + server.methods.getTop( function(top) { + reply(top).code(200); + }); + } + }); +}; \ No newline at end of file diff --git a/routes/database.js b/routes/database.js new file mode 100755 index 0000000..ba84daf --- /dev/null +++ b/routes/database.js @@ -0,0 +1,68 @@ +var Types = require('Joi'); +var _ = require('lodash'); + +var ua = require('universal-analytics'); +var visitor = ua('UA-27923958-9'); + +var Datastore = require('nedb'); +db = {}; +db.runners = new Datastore({ filename: 'db/runners', autoload: true }); +db.laps = new Datastore({ filename: 'db/laps', autoload: true }); + +module.exports = function(server) { + + server.method('getRunners', function (next) { + db.runners.find({ }, next); + }); + + server.method('getRunnerByID', function (bid, next) { + db.runners.findOne({ bid: bid }, next); + }); + + server.method('addRunner', function (runner, next) { + db.runners.insert(runner, next); + }); + + server.method('getLaps', function (next) { + db.laps.find({ }, next); + }); + + server.method('getLapsByID', function (bid, next) { + db.laps.findOne({ bid: bid }, next); + }); + + server.method('addLap', function (lap, next) { + db.laps.insert(lap, next); + }); + + server.method('getTop', function (next) { + var top = []; + db.runners.find({ }, function(err, runners) { + _.forEach(runners, function(runner, i) { + db.laps.find({ bid: runner.bid }, function(err, laps) { + if (laps) { + top.push({ + name: runner.name, + laps: laps.length + }) + } + if (i == runners.length-1) { + top = _.sortBy(top, 'laps').reverse(); + next(top); + } + }) + }) + }) + }); + + server.method('logLap', function (lap) { + visitor.event({ + ec:'Runner Tracking', + ea:'Runner Passed', + el: lap.time, + ev: lap.bid + }, function (err) { + if (err){console.log(err)}; + }); + }); +}; \ No newline at end of file diff --git a/routes/frontend.js b/routes/frontend.js new file mode 100755 index 0000000..1d1fb21 --- /dev/null +++ b/routes/frontend.js @@ -0,0 +1,29 @@ +module.exports = function(server) { + server.route({ + method: 'GET', + path: '/', + handler: { + file: { + path: 'public/index.html' + } + } + }); + server.route({ + method: 'GET', + path: '/admin', + handler: { + file: { + path: 'public/admin.html' + } + } + }); + server.route({ + method: 'GET', + path: '/public/{param*}', + handler: { + directory: { + path: 'public' + } + } + }); +}; \ No newline at end of file diff --git a/server.js b/server.js index 4b1b1b6..1b1d3e4 100755 --- a/server.js +++ b/server.js @@ -1,21 +1,16 @@ var Hapi = require('hapi'); -var backend = require('./backend'); -var frontend = require('./frontend'); -var bluetooth = require('./bluetooth'); -var Path = require('path'); var server = new Hapi.Server(); - server.connection({ port: 8080 }); -server.views({ - engines: { - html: require('handlebars') - }, - path: Path.join(__dirname, 'templates') -}); +var backend = require('./routes/backend')(server); +var database = require('./routes/database')(server); +var frontend = require('./routes/frontend')(server); +var bluetooth = require('./bluetooth')(server); +var Path = require('path'); -server.route(backend); -server.route(frontend); +server.start(function() { + console.log("Server started", server.info.uri); +}); -server.start(); \ No newline at end of file +module.exports = server; \ No newline at end of file diff --git a/templates/index.html b/templates/index.html deleted file mode 100644 index dcf4929..0000000 --- a/templates/index.html +++ /dev/null @@ -1,3 +0,0 @@ -hello - -{{ test }} \ No newline at end of file From e96bb234e3e81ed38e154588d71da177e160526d Mon Sep 17 00:00:00 2001 From: Paolo Memoli Date: Wed, 3 Jun 2015 02:48:41 +0200 Subject: [PATCH 03/25] updated readme --- README.md | 202 ++++-------------------------------------------------- 1 file changed, 12 insertions(+), 190 deletions(-) diff --git a/README.md b/README.md index ef4ee3c..be06d41 100755 --- a/README.md +++ b/README.md @@ -1,195 +1,17 @@ -**Making an API happy with hapi** +A simple app to track runners and count number of laps. -[Hapi](https://github.com/spumko/hapi) is a framework for rapidly building RESTful web services. Whether you are building a very simple set of RESTful services or a large scale, cache heavy, and secure set of services, [hapi](https://github.com/spumko/hapi/) has you covered. [Hapi](https://github.com/spumko/hapi/) will help get your server developed quickly with its wide range of configurable options. +- HAPI backend +- NEDB database +- Noble bluetooth detection +- Angular Frontend -***Building a Products API*** +Designed to be run remotely on a PI with a bluetooth 4.0 dongle + Bluetooth 4.0 tags on runners. -The following example will walk you through using hapi to build a RESTful set of services for creating and listing out products. To get started create a directory named _ProductsAPI_ and add a _package.json_ file to the directory that looks like the following. +to run: +if on linux/Pi: + - sudo apt-get install bluetooth bluez-utils libbluetooth-dev -```json -{ - "name": "ProductsAPI", - "version": "0.0.2", - "main": "server", - "engines": { - "node": ">=0.10.5" - }, - "dependencies": { - "hapi": "1.8.x", - "lout": "0.4.x", - "handlebars": "1.0.x" - }, - "private": "true" -} -``` - -Then run `npm install`. - -Create a _server.js_ file that will serve as the entry point for the service. Add the following contents to the _server.js_ file. - -```javascript -var Hapi = require('hapi'); -var routes = require('./routes'); - -var config = { }; -var server = new Hapi.Server('0.0.0.0', 8080, config); -server.pack.require({ lout: { endpoint: '/docs' } }, function (err) { - - if (err) { - console.log('Failed loading plugins'); - } -}); - -server.addRoutes(routes); - -server.start(); -``` - -In the _server.js_ code above a new instance of the hapi server is started using the [server options](http://spumko.github.io/resource/api/#server-options) specified in _config_. - -By registering the lout plugin, the [documentation generator](https://github.com/spumko/lout) will be enabled. The documentation generator provides a set of pages that explain what endpoints are available and the requirements for those endpoints. The documentation generator will use the validation rules you will create for each route to construct appropriate documentation pages under the _/docs_ path. - -[Hapi](https://github.com/spumko/hapi/) provides a function for adding a single route or an array of routes. In this example we are adding an array of routes from a routes module, go ahead and create a _routes.js_ file, which will contain the route information and handlers. When defining the routes we will also be specifying [validation requirements](http://spumko.github.io/resource/api/#hapi-types). Therefore, at the top of the file require _hapi_ and assign its _Types_ property to a local variable like below. - -```javascript -var Types = require('hapi').types; -``` - -For this example three routes will be created. Below is the code you should use to add the routes, go ahead and add the code to your _routes.js_ file. - -```javascript -module.exports = [{ - method: 'GET', - path: '/products', - config: { - handler: getProducts, - validate: { - query: { - name: Types.String() - } - } - } -}, { - method: 'GET', - path: '/products/{id}', - config: { - handler: getProduct - } -}, { - method: 'POST', - path: '/products', - config: { - handler: addProduct, - payload: 'parse', - validate: { - payload: { - name: Types.String().required().min(3) - } - } - } -}]; -``` - -The routes are exported as an array so that they can easily be included by the server implementation we added. For the products listing endpoint we are allowing a querystring parameter for name. When this querystring parameter exists then we will filter the products for those that have a matching name. - -The second route is a very simple route that demonstrates how a parameter can become part of the path definition. This route will return a product with the matching ID that’s requested. - -In the last route, the one used for creating a product, you will notice that extra validation requirements are added. The request body must contain a parameter for name that has a minimum of 3 characters. - -Next add the handlers to the _routes.js_ file. - -```javascript -function getProducts(request) { - - if (request.query.name) { - request.reply(findProducts(request.query.name)); - } - else { - request.reply(products); - } -} - -function findProducts(name) { - - return products.filter(function(product) { - return product.name.toLowerCase() === name.toLowerCase(); - }); -} - -function getProduct(request) { - - var product = products.filter(function(p) { - return p.id === parseInt(request.params.id); - }).pop(); - - request.reply(product); -} - -function addProduct(request) { - - var product = { - id: products[products.length - 1].id + 1, - name: request.payload.name - }; - - products.push(product); - - request.reply(product).created('/products/' + product.id); -} -``` - -As you can see in the handlers, hapi provides a simple way to add a response body by using the `request.reply` function. Also, in the instance when you have created an item you can use the `request.reply(product).created('/products/' + product.id)` functions to send a `201` response and set a custom `Location` header. - -Lastly, add a simple array to contain the products that the service will serve. - -```javascript -var products = [{ - id: 1, - name: 'Guitar' - }, - { - id: 2, - name: 'Banjo' - } -]; -``` - -***Running the server*** - -Go ahead and run ``npm start`` or ``node server.js`` to start the server. Now you can navigate to to see the documentation for the routes. To see a list of the products navigate to . Below is a screenshot of what the response looks like. - - - -Go ahead and append ?name=banjo to the URL to try searching for a product by name. - - - -Use curl or a REST console to create a product. Make a POST request to the products endpoint with a name in the body. Using curl the command looks like: ``curl http://localhost:8080/products -i -d "name=Ukelele"``. Below is an example of the response headers from making a request to create a product. - -```text -HTTP/1.1 201 Created -Content-Type: application/json; charset=utf-8 -Location: /products/3 -Content-Length: 25 -Cache-Control: no-cache -Date: Sat, 29 Jun 2013 16:44:42 GMT -Connection: keep-alive - -{"id":3,"name":"Ukelele"} -``` - - -Now if you navigate to the _Location_ specified in the response headers you should see the product that you created. - -Other features -There are a lot of different configuration features that you can add to the server. The extensive list can be found in the API documentation at . - -The built-in cache support has providers for memory, mongo and redis. Setting up cache is as simple as passing cache: true as part of the server configuration. - -Additionally, there are several configuration options available on a per route basis. The full list can be found at . For example, caching expiration times can also be configured on a per route basis. Also, you can have per-route authentication settings. - -***Conclusion*** - -By now you should have a decent understanding of what hapi has to offer. There are still many other features and options available to you when using hapi that is covered in the documentation. Please take a look at the github repository and feel free to provide any feedback you may have. - +all: + - npm install + - npm start \ No newline at end of file From 7731dcd77a897d3da5c520cb6ae6f93169f46e4c Mon Sep 17 00:00:00 2001 From: Paolo Memoli Date: Wed, 3 Jun 2015 02:50:16 +0200 Subject: [PATCH 04/25] typo in readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index be06d41..6f3ca0c 100755 --- a/README.md +++ b/README.md @@ -10,8 +10,8 @@ Designed to be run remotely on a PI with a bluetooth 4.0 dongle + Bluetooth 4.0 to run: if on linux/Pi: - - sudo apt-get install bluetooth bluez-utils libbluetooth-dev + 1. sudo apt-get install bluetooth bluez-utils libbluetooth-dev all: - - npm install - - npm start \ No newline at end of file + 1. npm install + 2. npm start \ No newline at end of file From 6440e65bea3dc313acef25d7d8fe0e5a454388a1 Mon Sep 17 00:00:00 2001 From: Paolo Memoli Date: Wed, 3 Jun 2015 02:52:36 +0200 Subject: [PATCH 05/25] updated readme' --- README.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 6f3ca0c..dbbca62 100755 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -A simple app to track runners and count number of laps. +#Runner Tracker +##A simple app to track runners and count number of laps. - HAPI backend - NEDB database @@ -9,9 +10,11 @@ Designed to be run remotely on a PI with a bluetooth 4.0 dongle + Bluetooth 4.0 to run: -if on linux/Pi: - 1. sudo apt-get install bluetooth bluez-utils libbluetooth-dev +## if on linux/Pi: -all: - 1. npm install - 2. npm start \ No newline at end of file +1. 'sudo apt-get install bluetooth bluez-utils libbluetooth-dev' + +## all: + +1. 'npm install' +2. 'npm start' \ No newline at end of file From 2feb858856b684815a4473ae648beac240ef5ce5 Mon Sep 17 00:00:00 2001 From: Paolo Memoli Date: Wed, 3 Jun 2015 02:54:19 +0200 Subject: [PATCH 06/25] removed old node modules' --- node_modules/.bin/handlebars | 1 - node_modules/handlebars/.npmignore | 25 - node_modules/handlebars/LICENSE | 19 - node_modules/handlebars/README.markdown | 438 --- node_modules/handlebars/bin/handlebars | 111 - .../handlebars/node_modules/.bin/uglifyjs | 1 - .../node_modules/optimist/.travis.yml | 4 - .../handlebars/node_modules/optimist/LICENSE | 21 - .../node_modules/optimist/example/bool.js | 10 - .../optimist/example/boolean_double.js | 7 - .../optimist/example/boolean_single.js | 7 - .../optimist/example/default_hash.js | 8 - .../optimist/example/default_singles.js | 7 - .../node_modules/optimist/example/divide.js | 8 - .../optimist/example/line_count.js | 20 - .../optimist/example/line_count_options.js | 29 - .../optimist/example/line_count_wrap.js | 29 - .../node_modules/optimist/example/nonopt.js | 4 - .../node_modules/optimist/example/reflect.js | 2 - .../node_modules/optimist/example/short.js | 3 - .../node_modules/optimist/example/string.js | 11 - .../optimist/example/usage-options.js | 19 - .../node_modules/optimist/example/xup.js | 10 - .../handlebars/node_modules/optimist/index.js | 343 --- .../optimist/node_modules/wordwrap/LICENSE | 18 - .../node_modules/wordwrap/README.markdown | 70 - .../node_modules/wordwrap/example/center.js | 10 - .../node_modules/wordwrap/example/meat.js | 3 - .../optimist/node_modules/wordwrap/index.js | 76 - .../node_modules/wordwrap/package.json | 63 - .../node_modules/wordwrap/test/break.js | 30 - .../node_modules/wordwrap/test/idleness.txt | 63 - .../node_modules/wordwrap/test/wrap.js | 31 - .../node_modules/optimist/package.json | 47 - .../node_modules/optimist/readme.markdown | 513 ---- .../node_modules/optimist/test/_.js | 71 - .../node_modules/optimist/test/_/argv.js | 2 - .../node_modules/optimist/test/_/bin.js | 3 - .../node_modules/optimist/test/parse.js | 446 --- .../node_modules/optimist/test/usage.js | 292 -- .../node_modules/uglify-js/.npmignore | 2 - .../node_modules/uglify-js/.travis.yml | 7 - .../handlebars/node_modules/uglify-js/LICENSE | 29 - .../node_modules/uglify-js/README.md | 588 ---- .../node_modules/uglify-js/bin/uglifyjs | 402 --- .../uglify-js/node_modules/async/LICENSE | 19 - .../uglify-js/node_modules/async/README.md | 1425 ---------- .../node_modules/async/component.json | 11 - .../uglify-js/node_modules/async/package.json | 61 - .../node_modules/uglify-js/package.json | 39 - .../uglify-js/test/compress/arrays.js | 12 - .../uglify-js/test/compress/blocks.js | 49 - .../uglify-js/test/compress/conditionals.js | 143 - .../uglify-js/test/compress/dead-code.js | 89 - .../uglify-js/test/compress/debugger.js | 24 - .../uglify-js/test/compress/drop-unused.js | 97 - .../uglify-js/test/compress/issue-105.js | 25 - .../uglify-js/test/compress/issue-12.js | 11 - .../uglify-js/test/compress/issue-143.js | 48 - .../uglify-js/test/compress/issue-22.js | 17 - .../uglify-js/test/compress/issue-44.js | 31 - .../uglify-js/test/compress/issue-59.js | 30 - .../uglify-js/test/compress/labels.js | 163 -- .../uglify-js/test/compress/loops.js | 123 - .../uglify-js/test/compress/properties.js | 54 - .../uglify-js/test/compress/sequences.js | 161 -- .../uglify-js/test/compress/switch.js | 260 -- .../uglify-js/test/compress/typeof.js | 25 - .../node_modules/uglify-js/test/run-tests.js | 170 -- .../node_modules/uglify-js/tools/node.js | 165 -- node_modules/handlebars/package.json | 102 - node_modules/handlebars/release-notes.md | 378 --- node_modules/hapi/.npmignore | 16 - node_modules/hapi/.travis.yml | 6 - node_modules/hapi/CONTRIBUTING.md | 14 - node_modules/hapi/LICENSE | 31 - node_modules/hapi/README.md | 15 - node_modules/hapi/images/hapi.png | Bin 42010 -> 0 bytes .../hapi/node_modules/boom/.npmignore | 18 - .../hapi/node_modules/boom/.travis.yml | 7 - node_modules/hapi/node_modules/boom/LICENSE | 28 - node_modules/hapi/node_modules/boom/README.md | 583 ---- .../hapi/node_modules/boom/images/boom.png | Bin 29479 -> 0 bytes node_modules/hapi/node_modules/boom/index.js | 1 - .../hapi/node_modules/boom/package.json | 64 - .../hapi/node_modules/boom/test/index.js | 615 ----- .../hapi/node_modules/catbox/.npmignore | 18 - .../hapi/node_modules/catbox/.travis.yml | 6 - node_modules/hapi/node_modules/catbox/LICENSE | 28 - .../hapi/node_modules/catbox/Makefile | 9 - .../hapi/node_modules/catbox/README.md | 136 - .../node_modules/catbox/examples/policy.js | 64 - .../node_modules/catbox/images/catbox.png | Bin 48752 -> 0 bytes .../hapi/node_modules/catbox/index.js | 1 - .../hapi/node_modules/catbox/package.json | 65 - .../hapi/node_modules/catbox/test/client.js | 393 --- .../hapi/node_modules/catbox/test/policy.js | 1861 ------------- .../hapi/node_modules/cryptiles/.npmignore | 18 - .../hapi/node_modules/cryptiles/.travis.yml | 5 - .../hapi/node_modules/cryptiles/LICENSE | 28 - .../hapi/node_modules/cryptiles/Makefile | 9 - .../hapi/node_modules/cryptiles/README.md | 14 - .../hapi/node_modules/cryptiles/index.js | 1 - .../hapi/node_modules/cryptiles/package.json | 65 - .../hapi/node_modules/cryptiles/test/index.js | 108 - .../hapi/node_modules/hoek/.npmignore | 18 - .../hapi/node_modules/hoek/.travis.yml | 7 - node_modules/hapi/node_modules/hoek/LICENSE | 31 - node_modules/hapi/node_modules/hoek/Makefile | 8 - node_modules/hapi/node_modules/hoek/README.md | 574 ---- .../hapi/node_modules/hoek/images/hoek.png | Bin 37939 -> 0 bytes node_modules/hapi/node_modules/hoek/index.js | 1 - .../hapi/node_modules/hoek/package.json | 60 - .../hapi/node_modules/hoek/test/escaper.js | 88 - .../hapi/node_modules/hoek/test/index.js | 2425 ----------------- .../node_modules/hoek/test/modules/test1.js | 1 - .../node_modules/hoek/test/modules/test2.js | 1 - .../node_modules/hoek/test/modules/test3.js | 1 - .../hapi/node_modules/iron/.npmignore | 18 - .../hapi/node_modules/iron/.travis.yml | 6 - node_modules/hapi/node_modules/iron/LICENSE | 28 - node_modules/hapi/node_modules/iron/Makefile | 9 - node_modules/hapi/node_modules/iron/README.md | 175 -- .../hapi/node_modules/iron/images/iron.png | Bin 5973 -> 0 bytes .../hapi/node_modules/iron/images/logo.png | Bin 28956 -> 0 bytes node_modules/hapi/node_modules/iron/index.js | 1 - .../hapi/node_modules/iron/package.json | 67 - .../hapi/node_modules/iron/test/index.js | 521 ---- node_modules/hapi/node_modules/joi/.npmignore | 20 - .../hapi/node_modules/joi/.travis.yml | 24 - node_modules/hapi/node_modules/joi/LICENSE | 28 - node_modules/hapi/node_modules/joi/README.md | 1447 ---------- .../hapi/node_modules/joi/images/joi.png | Bin 30662 -> 0 bytes .../node_modules/joi/images/validation.png | Bin 117266 -> 0 bytes node_modules/hapi/node_modules/joi/index.js | 1 - .../hapi/node_modules/joi/package.json | 69 - .../hapi/node_modules/joi/test/index.js | 1610 ----------- .../hapi/node_modules/shot/.npmignore | 18 - .../hapi/node_modules/shot/.travis.yml | 6 - node_modules/hapi/node_modules/shot/LICENSE | 29 - node_modules/hapi/node_modules/shot/README.md | 45 - .../hapi/node_modules/shot/examples/http.js | 32 - .../hapi/node_modules/shot/images/shot.png | Bin 39211 -> 0 bytes node_modules/hapi/node_modules/shot/index.js | 1 - .../hapi/node_modules/shot/package.json | 68 - .../hapi/node_modules/shot/test/index.js | 599 ---- node_modules/hapi/package.json | 85 - 147 files changed, 19984 deletions(-) delete mode 120000 node_modules/.bin/handlebars delete mode 100644 node_modules/handlebars/.npmignore delete mode 100644 node_modules/handlebars/LICENSE delete mode 100644 node_modules/handlebars/README.markdown delete mode 100755 node_modules/handlebars/bin/handlebars delete mode 120000 node_modules/handlebars/node_modules/.bin/uglifyjs delete mode 100644 node_modules/handlebars/node_modules/optimist/.travis.yml delete mode 100644 node_modules/handlebars/node_modules/optimist/LICENSE delete mode 100644 node_modules/handlebars/node_modules/optimist/example/bool.js delete mode 100644 node_modules/handlebars/node_modules/optimist/example/boolean_double.js delete mode 100644 node_modules/handlebars/node_modules/optimist/example/boolean_single.js delete mode 100644 node_modules/handlebars/node_modules/optimist/example/default_hash.js delete mode 100644 node_modules/handlebars/node_modules/optimist/example/default_singles.js delete mode 100644 node_modules/handlebars/node_modules/optimist/example/divide.js delete mode 100644 node_modules/handlebars/node_modules/optimist/example/line_count.js delete mode 100644 node_modules/handlebars/node_modules/optimist/example/line_count_options.js delete mode 100644 node_modules/handlebars/node_modules/optimist/example/line_count_wrap.js delete mode 100644 node_modules/handlebars/node_modules/optimist/example/nonopt.js delete mode 100644 node_modules/handlebars/node_modules/optimist/example/reflect.js delete mode 100644 node_modules/handlebars/node_modules/optimist/example/short.js delete mode 100644 node_modules/handlebars/node_modules/optimist/example/string.js delete mode 100644 node_modules/handlebars/node_modules/optimist/example/usage-options.js delete mode 100644 node_modules/handlebars/node_modules/optimist/example/xup.js delete mode 100644 node_modules/handlebars/node_modules/optimist/index.js delete mode 100644 node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/LICENSE delete mode 100644 node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/README.markdown delete mode 100644 node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/example/center.js delete mode 100644 node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/example/meat.js delete mode 100644 node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/index.js delete mode 100644 node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/package.json delete mode 100644 node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/test/break.js delete mode 100644 node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/test/idleness.txt delete mode 100644 node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/test/wrap.js delete mode 100644 node_modules/handlebars/node_modules/optimist/package.json delete mode 100644 node_modules/handlebars/node_modules/optimist/readme.markdown delete mode 100644 node_modules/handlebars/node_modules/optimist/test/_.js delete mode 100644 node_modules/handlebars/node_modules/optimist/test/_/argv.js delete mode 100755 node_modules/handlebars/node_modules/optimist/test/_/bin.js delete mode 100644 node_modules/handlebars/node_modules/optimist/test/parse.js delete mode 100644 node_modules/handlebars/node_modules/optimist/test/usage.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/.npmignore delete mode 100644 node_modules/handlebars/node_modules/uglify-js/.travis.yml delete mode 100644 node_modules/handlebars/node_modules/uglify-js/LICENSE delete mode 100644 node_modules/handlebars/node_modules/uglify-js/README.md delete mode 100755 node_modules/handlebars/node_modules/uglify-js/bin/uglifyjs delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/async/LICENSE delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/async/README.md delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/async/component.json delete mode 100644 node_modules/handlebars/node_modules/uglify-js/node_modules/async/package.json delete mode 100644 node_modules/handlebars/node_modules/uglify-js/package.json delete mode 100644 node_modules/handlebars/node_modules/uglify-js/test/compress/arrays.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/test/compress/blocks.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/test/compress/conditionals.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/test/compress/dead-code.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/test/compress/debugger.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/test/compress/drop-unused.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/test/compress/issue-105.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/test/compress/issue-12.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/test/compress/issue-143.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/test/compress/issue-22.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/test/compress/issue-44.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/test/compress/issue-59.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/test/compress/labels.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/test/compress/loops.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/test/compress/properties.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/test/compress/sequences.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/test/compress/switch.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/test/compress/typeof.js delete mode 100755 node_modules/handlebars/node_modules/uglify-js/test/run-tests.js delete mode 100644 node_modules/handlebars/node_modules/uglify-js/tools/node.js delete mode 100644 node_modules/handlebars/package.json delete mode 100644 node_modules/handlebars/release-notes.md delete mode 100644 node_modules/hapi/.npmignore delete mode 100755 node_modules/hapi/.travis.yml delete mode 100755 node_modules/hapi/CONTRIBUTING.md delete mode 100755 node_modules/hapi/LICENSE delete mode 100755 node_modules/hapi/README.md delete mode 100755 node_modules/hapi/images/hapi.png delete mode 100644 node_modules/hapi/node_modules/boom/.npmignore delete mode 100755 node_modules/hapi/node_modules/boom/.travis.yml delete mode 100755 node_modules/hapi/node_modules/boom/LICENSE delete mode 100755 node_modules/hapi/node_modules/boom/README.md delete mode 100755 node_modules/hapi/node_modules/boom/images/boom.png delete mode 100755 node_modules/hapi/node_modules/boom/index.js delete mode 100644 node_modules/hapi/node_modules/boom/package.json delete mode 100755 node_modules/hapi/node_modules/boom/test/index.js delete mode 100644 node_modules/hapi/node_modules/catbox/.npmignore delete mode 100755 node_modules/hapi/node_modules/catbox/.travis.yml delete mode 100755 node_modules/hapi/node_modules/catbox/LICENSE delete mode 100755 node_modules/hapi/node_modules/catbox/Makefile delete mode 100755 node_modules/hapi/node_modules/catbox/README.md delete mode 100755 node_modules/hapi/node_modules/catbox/examples/policy.js delete mode 100755 node_modules/hapi/node_modules/catbox/images/catbox.png delete mode 100755 node_modules/hapi/node_modules/catbox/index.js delete mode 100644 node_modules/hapi/node_modules/catbox/package.json delete mode 100755 node_modules/hapi/node_modules/catbox/test/client.js delete mode 100755 node_modules/hapi/node_modules/catbox/test/policy.js delete mode 100644 node_modules/hapi/node_modules/cryptiles/.npmignore delete mode 100755 node_modules/hapi/node_modules/cryptiles/.travis.yml delete mode 100755 node_modules/hapi/node_modules/cryptiles/LICENSE delete mode 100755 node_modules/hapi/node_modules/cryptiles/Makefile delete mode 100644 node_modules/hapi/node_modules/cryptiles/README.md delete mode 100755 node_modules/hapi/node_modules/cryptiles/index.js delete mode 100644 node_modules/hapi/node_modules/cryptiles/package.json delete mode 100755 node_modules/hapi/node_modules/cryptiles/test/index.js delete mode 100644 node_modules/hapi/node_modules/hoek/.npmignore delete mode 100755 node_modules/hapi/node_modules/hoek/.travis.yml delete mode 100755 node_modules/hapi/node_modules/hoek/LICENSE delete mode 100755 node_modules/hapi/node_modules/hoek/Makefile delete mode 100755 node_modules/hapi/node_modules/hoek/README.md delete mode 100755 node_modules/hapi/node_modules/hoek/images/hoek.png delete mode 100755 node_modules/hapi/node_modules/hoek/index.js delete mode 100644 node_modules/hapi/node_modules/hoek/package.json delete mode 100755 node_modules/hapi/node_modules/hoek/test/escaper.js delete mode 100755 node_modules/hapi/node_modules/hoek/test/index.js delete mode 100755 node_modules/hapi/node_modules/hoek/test/modules/test1.js delete mode 100755 node_modules/hapi/node_modules/hoek/test/modules/test2.js delete mode 100755 node_modules/hapi/node_modules/hoek/test/modules/test3.js delete mode 100644 node_modules/hapi/node_modules/iron/.npmignore delete mode 100755 node_modules/hapi/node_modules/iron/.travis.yml delete mode 100755 node_modules/hapi/node_modules/iron/LICENSE delete mode 100755 node_modules/hapi/node_modules/iron/Makefile delete mode 100755 node_modules/hapi/node_modules/iron/README.md delete mode 100755 node_modules/hapi/node_modules/iron/images/iron.png delete mode 100755 node_modules/hapi/node_modules/iron/images/logo.png delete mode 100755 node_modules/hapi/node_modules/iron/index.js delete mode 100644 node_modules/hapi/node_modules/iron/package.json delete mode 100755 node_modules/hapi/node_modules/iron/test/index.js delete mode 100644 node_modules/hapi/node_modules/joi/.npmignore delete mode 100755 node_modules/hapi/node_modules/joi/.travis.yml delete mode 100755 node_modules/hapi/node_modules/joi/LICENSE delete mode 100644 node_modules/hapi/node_modules/joi/README.md delete mode 100755 node_modules/hapi/node_modules/joi/images/joi.png delete mode 100755 node_modules/hapi/node_modules/joi/images/validation.png delete mode 100755 node_modules/hapi/node_modules/joi/index.js delete mode 100644 node_modules/hapi/node_modules/joi/package.json delete mode 100755 node_modules/hapi/node_modules/joi/test/index.js delete mode 100644 node_modules/hapi/node_modules/shot/.npmignore delete mode 100755 node_modules/hapi/node_modules/shot/.travis.yml delete mode 100755 node_modules/hapi/node_modules/shot/LICENSE delete mode 100755 node_modules/hapi/node_modules/shot/README.md delete mode 100755 node_modules/hapi/node_modules/shot/examples/http.js delete mode 100755 node_modules/hapi/node_modules/shot/images/shot.png delete mode 100755 node_modules/hapi/node_modules/shot/index.js delete mode 100644 node_modules/hapi/node_modules/shot/package.json delete mode 100755 node_modules/hapi/node_modules/shot/test/index.js delete mode 100644 node_modules/hapi/package.json diff --git a/node_modules/.bin/handlebars b/node_modules/.bin/handlebars deleted file mode 120000 index fb7d090..0000000 --- a/node_modules/.bin/handlebars +++ /dev/null @@ -1 +0,0 @@ -../handlebars/bin/handlebars \ No newline at end of file diff --git a/node_modules/handlebars/.npmignore b/node_modules/handlebars/.npmignore deleted file mode 100644 index f10592c..0000000 --- a/node_modules/handlebars/.npmignore +++ /dev/null @@ -1,25 +0,0 @@ -.DS_Store -.gitignore -.rvmrc -.eslintrc -.travis.yml -.rspec -Gemfile -Gemfile.lock -Rakefile -Gruntfile.js -*.gemspec -*.nuspec -*.log -bench/* -configurations/* -components/* -coverage/* -dist/cdnjs/* -dist/components/* -spec/* -src/* -tasks/* -tmp/* -publish/* -vendor/* diff --git a/node_modules/handlebars/LICENSE b/node_modules/handlebars/LICENSE deleted file mode 100644 index a2d22cb..0000000 --- a/node_modules/handlebars/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (C) 2011-2014 by Yehuda Katz - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/node_modules/handlebars/README.markdown b/node_modules/handlebars/README.markdown deleted file mode 100644 index d6aa6bd..0000000 --- a/node_modules/handlebars/README.markdown +++ /dev/null @@ -1,438 +0,0 @@ -[![Travis Build Status](https://img.shields.io/travis/wycats/handlebars.js/master.svg)](https://travis-ci.org/wycats/handlebars.js) -[![Selenium Test Status](https://saucelabs.com/buildstatus/handlebars)](https://saucelabs.com/u/handlebars) - -Handlebars.js -============= - -Handlebars.js is an extension to the [Mustache templating -language](http://mustache.github.com/) created by Chris Wanstrath. -Handlebars.js and Mustache are both logicless templating languages that -keep the view and the code separated like we all know they should be. - -Checkout the official Handlebars docs site at -[http://www.handlebarsjs.com](http://www.handlebarsjs.com). - -Installing ----------- -Installing Handlebars is easy. Simply download the package [from the official site](http://handlebarsjs.com/) or the [bower repository][bower-repo] and add it to your web pages (you should usually use the most recent version). - -For web browsers, a free CDN is available at [jsDelivr](http://www.jsdelivr.com/#!handlebarsjs). Advanced usage, such as [version aliasing & concocting](https://github.com/jsdelivr/jsdelivr#usage), is available. - -Alternatively, if you prefer having the latest version of handlebars from -the 'master' branch, passing builds of the 'master' branch are automatically -published to S3. You may download the latest passing master build by grabbing -a `handlebars-latest.js` file from the [builds page][builds-page]. When the -build is published, it is also available as a `handlebars-gitSHA.js` file on -the builds page if you need a version to refer to others. -`handlebars-runtime.js` builds are also available. - -**Note**: The S3 builds page is provided as a convenience for the community, -but you should not use it for hosting Handlebars in production. - -Usage ------ -In general, the syntax of Handlebars.js templates is a superset -of Mustache templates. For basic syntax, check out the [Mustache -manpage](http://mustache.github.com/mustache.5.html). - -Once you have a template, use the `Handlebars.compile` method to compile -the template into a function. The generated function takes a context -argument, which will be used to render the template. - -```js -var source = "

Hello, my name is {{name}}. I am from {{hometown}}. I have " + - "{{kids.length}} kids:

" + - "
    {{#kids}}
  • {{name}} is {{age}}
  • {{/kids}}
"; -var template = Handlebars.compile(source); - -var data = { "name": "Alan", "hometown": "Somewhere, TX", - "kids": [{"name": "Jimmy", "age": "12"}, {"name": "Sally", "age": "4"}]}; -var result = template(data); - -// Would render: -//

Hello, my name is Alan. I am from Somewhere, TX. I have 2 kids:

-//
    -//
  • Jimmy is 12
  • -//
  • Sally is 4
  • -//
-``` - - -Registering Helpers -------------------- - -You can register helpers that Handlebars will use when evaluating your -template. Here's an example, which assumes that your objects have a URL -embedded in them, as well as the text for a link: - -```js -Handlebars.registerHelper('link_to', function() { - return new Handlebars.SafeString("" + Handlebars.Utils.escapeExpression(this.body) + ""); -}); - -var context = { posts: [{url: "/hello-world", body: "Hello World!"}] }; -var source = "
    {{#posts}}
  • {{link_to}}
  • {{/posts}}
" - -var template = Handlebars.compile(source); -template(context); - -// Would render: -// -// -``` - -Helpers take precedence over fields defined on the context. To access a field -that is masked by a helper, a path reference may be used. In the example above -a field named `link_to` on the `context` object would be referenced using: - -``` -{{./link_to}} -``` - -Escaping --------- - -By default, the `{{expression}}` syntax will escape its contents. This -helps to protect you against accidental XSS problems caused by malicious -data passed from the server as JSON. - -To explicitly *not* escape the contents, use the triple-mustache -(`{{{}}}`). You have seen this used in the above example. - - -Differences Between Handlebars.js and Mustache ----------------------------------------------- -Handlebars.js adds a couple of additional features to make writing -templates easier and also changes a tiny detail of how partials work. - -### Paths - -Handlebars.js supports an extended expression syntax that we call paths. -Paths are made up of typical expressions and `.` characters. Expressions -allow you to not only display data from the current context, but to -display data from contexts that are descendants and ancestors of the -current context. - -To display data from descendant contexts, use the `.` character. So, for -example, if your data were structured like: - -```js -var data = {"person": { "name": "Alan" }, "company": {"name": "Rad, Inc." } }; -``` - -You could display the person's name from the top-level context with the -following expression: - -``` -{{person.name}} -``` - -You can backtrack using `../`. For example, if you've already traversed -into the person object you could still display the company's name with -an expression like `{{../company.name}}`, so: - -``` -{{#with person}}{{name}} - {{../company.name}}{{/with}} -``` - -would render: - -``` -Alan - Rad, Inc. -``` - -### Strings - -When calling a helper, you can pass paths or Strings as parameters. For -instance: - -```js -Handlebars.registerHelper('link_to', function(title, options) { - return "" + title + "!" -}); - -var context = { posts: [{url: "/hello-world", body: "Hello World!"}] }; -var source = '
    {{#posts}}
  • {{{link_to "Post"}}}
  • {{/posts}}
' - -var template = Handlebars.compile(source); -template(context); - -// Would render: -// -// -``` - -When you pass a String as a parameter to a helper, the literal String -gets passed to the helper function. - - -### Block Helpers - -Handlebars.js also adds the ability to define block helpers. Block -helpers are functions that can be called from anywhere in the template. -Here's an example: - -```js -var source = "
    {{#people}}
  • {{#link}}{{name}}{{/link}}
  • {{/people}}
"; -Handlebars.registerHelper('link', function(options) { - return '' + options.fn(this) + ''; -}); -var template = Handlebars.compile(source); - -var data = { "people": [ - { "name": "Alan", "id": 1 }, - { "name": "Yehuda", "id": 2 } - ]}; -template(data); - -// Should render: -// -``` - -Whenever the block helper is called it is given one or more parameters, -any arguments that are passed into the helper in the call, and an `options` -object containing the `fn` function which executes the block's child. -The block's current context may be accessed through `this`. - -Block helpers have the same syntax as mustache sections but should not be -confused with one another. Sections are akin to an implicit `each` or -`with` statement depending on the input data and helpers are explicit -pieces of code that are free to implement whatever behavior they like. -The [mustache spec](http://mustache.github.io/mustache.5.html) -defines the exact behavior of sections. In the case of name conflicts, -helpers are given priority. - -### Partials - -You can register additional templates as partials, which will be used by -Handlebars when it encounters a partial (`{{> partialName}}`). Partials -can either be String templates or compiled template functions. Here's an -example: - -```js -var source = "
    {{#people}}
  • {{> link}}
  • {{/people}}
"; - -Handlebars.registerPartial('link', '{{name}}') -var template = Handlebars.compile(source); - -var data = { "people": [ - { "name": "Alan", "id": 1 }, - { "name": "Yehuda", "id": 2 } - ]}; - -template(data); - -// Should render: -// -``` - -Partials can also accept parameters - -```js -var source = "
{{> roster rosterProperties people=listOfPeople}}
"; - -Handlebars.registerPartial('roster', '

{{rosterName}}

{{#people}}{{id}}: {{name}}{{/people}}') -var template = Handlebars.compile(source); - -var data = { - "listOfPeople": [ - { "name": "Alan", "id": 1 }, - { "name": "Yehuda", "id": 2 } - ], - "rosterProperties": { - "rosterName": "Cool People" - } -}; - -template(data); - -// Should render: -//
-//

Cool People

-// 1: Alan -// 2: Yehuda -//
- -``` - -### Comments - -You can add comments to your templates with the following syntax: - -```js -{{! This is a comment }} -``` - -You can also use real html comments if you want them to end up in the output. - -```html -
- {{! This comment will not end up in the output }} - -
-``` - - -### Compatibility - -There are a few Mustache behaviors that Handlebars does not implement. -- Handlebars deviates from Mustache slightly in that it does not perform recursive lookup by default. The compile time `compat` flag must be set to enable this functionality. Users should note that there is a performance cost for enabling this flag. The exact cost varies by template, but it's recommended that performance sensitive operations should avoid this mode and instead opt for explicit path references. -- The optional Mustache-style lambdas are not supported. Instead Handlebars provides it's own lambda resolution that follows the behaviors of helpers. -- Alternative delimeters are not supported. - - -Precompiling Templates ----------------------- - -Handlebars allows templates to be precompiled and included as javascript -code rather than the handlebars template allowing for faster startup time. - -### Installation -The precompiler script may be installed via npm using the `npm install -g handlebars` -command. - -### Usage - -
-Precompile handlebar templates.
-Usage: handlebars template...
-
-Options:
-  -a, --amd            Create an AMD format function (allows loading with RequireJS)          [boolean]
-  -f, --output         Output File                                                            [string]
-  -k, --known          Known helpers                                                          [string]
-  -o, --knownOnly      Known helpers only                                                     [boolean]
-  -m, --min            Minimize output                                                        [boolean]
-  -s, --simple         Output template function only.                                         [boolean]
-  -r, --root           Template root. Base value that will be stripped from template names.   [string]
-  -c, --commonjs       Exports CommonJS style, path to Handlebars module                      [string]
-  -h, --handlebarPath  Path to handlebar.js (only valid for amd-style)                        [string]
-  -n, --namespace      Template namespace                                                     [string]
-  -p, --partial        Compiling a partial template                                           [boolean]
-  -d, --data           Include data when compiling                                            [boolean]
-  -e, --extension      Template extension.                                                    [string]
-  -b, --bom            Removes the BOM (Byte Order Mark) from the beginning of the templates. [boolean]
-
- -If using the precompiler's normal mode, the resulting templates will be -stored to the `Handlebars.templates` object using the relative template -name sans the extension. These templates may be executed in the same -manner as templates. - -If using the simple mode the precompiler will generate a single -javascript method. To execute this method it must be passed to -the `Handlebars.template` method and the resulting object may be used as normal. - -### Optimizations - -- Rather than using the full _handlebars.js_ library, implementations that - do not need to compile templates at runtime may include _handlebars.runtime.js_ - whose min+gzip size is approximately 1k. -- If a helper is known to exist in the target environment they may be defined - using the `--known name` argument may be used to optimize accesses to these - helpers for size and speed. -- When all helpers are known in advance the `--knownOnly` argument may be used - to optimize all block helper references. -- Implementations that do not use `@data` variables can improve performance of - iteration centric templates by specifying `{data: false}` in the compiler options. - -Supported Environments ----------------------- - -Handlebars has been designed to work in any ECMAScript 3 environment. This includes - -- Node.js -- Chrome -- Firefox -- Safari 5+ -- Opera 11+ -- IE 6+ - -Older versions and other runtimes are likely to work but have not been formally -tested. The compiler requires `JSON.stringify` to be implemented natively or via a polyfill. If using the precompiler this is not necessary. - -[![Selenium Test Status](https://saucelabs.com/browser-matrix/handlebars.svg)](https://saucelabs.com/u/handlebars) - -Performance ------------ - -In a rough performance test, precompiled Handlebars.js templates (in -the original version of Handlebars.js) rendered in about half the -time of Mustache templates. It would be a shame if it were any other -way, since they were precompiled, but the difference in architecture -does have some big performance advantages. Justin Marney, a.k.a. -[gotascii](http://github.com/gotascii), confirmed that with an -[independent test](http://sorescode.com/2010/09/12/benchmarks.html). The -rewritten Handlebars (current version) is faster than the old version, -with many [performance tests](https://travis-ci.org/wycats/handlebars.js/builds/33392182#L538) being 5 to 7 times faster than the Mustache equivalent. - - -Upgrading ---------- - -See [release-notes.md](https://github.com/wycats/handlebars.js/blob/master/release-notes.md) for upgrade notes. - -Known Issues ------------- - -See [FAQ.md](https://github.com/wycats/handlebars.js/blob/master/FAQ.md) for known issues and common pitfalls. - - -Handlebars in the Wild ----------------------- - -* [Assemble](http://assemble.io), by [@jonschlinkert](https://github.com/jonschlinkert) - and [@doowb](https://github.com/doowb), is a static site generator that uses Handlebars.js - as its template engine. -* [CoSchedule](http://coschedule.com) An editorial calendar for WordPress that uses Handlebars.js -* [dashbars](https://github.com/pismute/dashbars) A modern helper library for Handlebars.js. -* [Ember.js](http://www.emberjs.com) makes Handlebars.js the primary way to - structure your views, also with automatic data binding support. -* [Ghost](https://ghost.org/) Just a blogging platform. -* [handlebars_assets](http://github.com/leshill/handlebars_assets): A Rails Asset Pipeline gem - from Les Hill (@leshill). -* [handlebars-helpers](https://github.com/assemble/handlebars-helpers) is an extensive library - with 100+ handlebars helpers. -* [handlebars-layouts](https://github.com/shannonmoeller/handlebars-layouts) is a set of helpers which implement extendible and embeddable layout blocks as seen in other popular templating languages. -* [hbs](http://github.com/donpark/hbs): An Express.js view engine adapter for Handlebars.js, - from Don Park. -* [koa-hbs](https://github.com/jwilm/koa-hbs): [koa](https://github.com/koajs/koa) generator based - renderer for Handlebars.js. -* [jblotus](http://github.com/jblotus) created [http://tryhandlebarsjs.com](http://tryhandlebarsjs.com) - for anyone who would like to try out Handlebars.js in their browser. -* [jQuery plugin](http://71104.github.io/jquery-handlebars/): allows you to use - Handlebars.js with [jQuery](http://jquery.com/). -* [Lumbar](http://walmartlabs.github.io/lumbar) provides easy module-based template management for - handlebars projects. -* [sammy.js](http://github.com/quirkey/sammy) by Aaron Quint, a.k.a. quirkey, - supports Handlebars.js as one of its template plugins. -* [SproutCore](http://www.sproutcore.com) uses Handlebars.js as its main - templating engine, extending it with automatic data binding support. -* [YUI](http://yuilibrary.com/yui/docs/handlebars/) implements a port of handlebars -* [Swag](https://github.com/elving/swag) by [@elving](https://github.com/elving) is a growing collection of helpers for handlebars.js. Give your handlebars.js templates some swag son! -* [DOMBars](https://github.com/blakeembrey/dombars) is a DOM-based templating engine built on the Handlebars parser and runtime - -External Resources ------------------- - -* [Gist about Synchronous and asynchronous loading of external handlebars templates](https://gist.github.com/2287070) - -Have a project using Handlebars? Send us a [pull request][pull-request]! - -License -------- -Handlebars.js is released under the MIT license. - -[bower-repo]: https://github.com/components/handlebars.js -[builds-page]: http://builds.handlebarsjs.com.s3.amazonaws.com/bucket-listing.html?sort=lastmod&sortdir=desc -[pull-request]: https://github.com/wycats/handlebars.js/pull/new/master diff --git a/node_modules/handlebars/bin/handlebars b/node_modules/handlebars/bin/handlebars deleted file mode 100755 index 4ed98b3..0000000 --- a/node_modules/handlebars/bin/handlebars +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env node - -var optimist = require('optimist') - .usage('Precompile handlebar templates.\nUsage: $0 [template|directory]...', { - 'f': { - 'type': 'string', - 'description': 'Output File', - 'alias': 'output' - }, - 'map': { - 'type': 'string', - 'description': 'Source Map File' - }, - 'a': { - 'type': 'boolean', - 'description': 'Exports amd style (require.js)', - 'alias': 'amd' - }, - 'c': { - 'type': 'string', - 'description': 'Exports CommonJS style, path to Handlebars module', - 'alias': 'commonjs', - 'default': null - }, - 'h': { - 'type': 'string', - 'description': 'Path to handlebar.js (only valid for amd-style)', - 'alias': 'handlebarPath', - 'default': '' - }, - 'k': { - 'type': 'string', - 'description': 'Known helpers', - 'alias': 'known' - }, - 'o': { - 'type': 'boolean', - 'description': 'Known helpers only', - 'alias': 'knownOnly' - }, - 'm': { - 'type': 'boolean', - 'description': 'Minimize output', - 'alias': 'min' - }, - 'n': { - 'type': 'string', - 'description': 'Template namespace', - 'alias': 'namespace', - 'default': 'Handlebars.templates' - }, - 's': { - 'type': 'boolean', - 'description': 'Output template function only.', - 'alias': 'simple' - }, - 'r': { - 'type': 'string', - 'description': 'Template root. Base value that will be stripped from template names.', - 'alias': 'root' - }, - 'p' : { - 'type': 'boolean', - 'description': 'Compiling a partial template', - 'alias': 'partial' - }, - 'd' : { - 'type': 'boolean', - 'description': 'Include data when compiling', - 'alias': 'data' - }, - 'e': { - 'type': 'string', - 'description': 'Template extension.', - 'alias': 'extension', - 'default': 'handlebars' - }, - 'b': { - 'type': 'boolean', - 'description': 'Removes the BOM (Byte Order Mark) from the beginning of the templates.', - 'alias': 'bom' - }, - 'v': { - 'type': 'boolean', - 'description': 'Prints the current compiler version', - 'alias': 'version' - }, - - 'help': { - 'type': 'boolean', - 'description': 'Outputs this message' - } - }) - - .check(function(argv) { - if (argv.version) { - return; - } - }); - - -var argv = optimist.argv; -argv.templates = argv._; -delete argv._; - -if (argv.help || (!argv.templates.length && !argv.version)) { - optimist.showHelp(); - return; -} - -return require('../dist/cjs/precompiler').cli(argv); diff --git a/node_modules/handlebars/node_modules/.bin/uglifyjs b/node_modules/handlebars/node_modules/.bin/uglifyjs deleted file mode 120000 index fef3468..0000000 --- a/node_modules/handlebars/node_modules/.bin/uglifyjs +++ /dev/null @@ -1 +0,0 @@ -../uglify-js/bin/uglifyjs \ No newline at end of file diff --git a/node_modules/handlebars/node_modules/optimist/.travis.yml b/node_modules/handlebars/node_modules/optimist/.travis.yml deleted file mode 100644 index cc4dba2..0000000 --- a/node_modules/handlebars/node_modules/optimist/.travis.yml +++ /dev/null @@ -1,4 +0,0 @@ -language: node_js -node_js: - - "0.8" - - "0.10" diff --git a/node_modules/handlebars/node_modules/optimist/LICENSE b/node_modules/handlebars/node_modules/optimist/LICENSE deleted file mode 100644 index 432d1ae..0000000 --- a/node_modules/handlebars/node_modules/optimist/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -Copyright 2010 James Halliday (mail@substack.net) - -This project is free software released under the MIT/X11 license: - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/node_modules/handlebars/node_modules/optimist/example/bool.js b/node_modules/handlebars/node_modules/optimist/example/bool.js deleted file mode 100644 index a998fb7..0000000 --- a/node_modules/handlebars/node_modules/optimist/example/bool.js +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env node -var util = require('util'); -var argv = require('optimist').argv; - -if (argv.s) { - util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: '); -} -console.log( - (argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '') -); diff --git a/node_modules/handlebars/node_modules/optimist/example/boolean_double.js b/node_modules/handlebars/node_modules/optimist/example/boolean_double.js deleted file mode 100644 index a35a7e6..0000000 --- a/node_modules/handlebars/node_modules/optimist/example/boolean_double.js +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env node -var argv = require('optimist') - .boolean(['x','y','z']) - .argv -; -console.dir([ argv.x, argv.y, argv.z ]); -console.dir(argv._); diff --git a/node_modules/handlebars/node_modules/optimist/example/boolean_single.js b/node_modules/handlebars/node_modules/optimist/example/boolean_single.js deleted file mode 100644 index 017bb68..0000000 --- a/node_modules/handlebars/node_modules/optimist/example/boolean_single.js +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env node -var argv = require('optimist') - .boolean('v') - .argv -; -console.dir(argv.v); -console.dir(argv._); diff --git a/node_modules/handlebars/node_modules/optimist/example/default_hash.js b/node_modules/handlebars/node_modules/optimist/example/default_hash.js deleted file mode 100644 index ade7768..0000000 --- a/node_modules/handlebars/node_modules/optimist/example/default_hash.js +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env node - -var argv = require('optimist') - .default({ x : 10, y : 10 }) - .argv -; - -console.log(argv.x + argv.y); diff --git a/node_modules/handlebars/node_modules/optimist/example/default_singles.js b/node_modules/handlebars/node_modules/optimist/example/default_singles.js deleted file mode 100644 index d9b1ff4..0000000 --- a/node_modules/handlebars/node_modules/optimist/example/default_singles.js +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env node -var argv = require('optimist') - .default('x', 10) - .default('y', 10) - .argv -; -console.log(argv.x + argv.y); diff --git a/node_modules/handlebars/node_modules/optimist/example/divide.js b/node_modules/handlebars/node_modules/optimist/example/divide.js deleted file mode 100644 index 5e2ee82..0000000 --- a/node_modules/handlebars/node_modules/optimist/example/divide.js +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env node - -var argv = require('optimist') - .usage('Usage: $0 -x [num] -y [num]') - .demand(['x','y']) - .argv; - -console.log(argv.x / argv.y); diff --git a/node_modules/handlebars/node_modules/optimist/example/line_count.js b/node_modules/handlebars/node_modules/optimist/example/line_count.js deleted file mode 100644 index b5f95bf..0000000 --- a/node_modules/handlebars/node_modules/optimist/example/line_count.js +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env node -var argv = require('optimist') - .usage('Count the lines in a file.\nUsage: $0') - .demand('f') - .alias('f', 'file') - .describe('f', 'Load a file') - .argv -; - -var fs = require('fs'); -var s = fs.createReadStream(argv.file); - -var lines = 0; -s.on('data', function (buf) { - lines += buf.toString().match(/\n/g).length; -}); - -s.on('end', function () { - console.log(lines); -}); diff --git a/node_modules/handlebars/node_modules/optimist/example/line_count_options.js b/node_modules/handlebars/node_modules/optimist/example/line_count_options.js deleted file mode 100644 index d9ac709..0000000 --- a/node_modules/handlebars/node_modules/optimist/example/line_count_options.js +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env node -var argv = require('optimist') - .usage('Count the lines in a file.\nUsage: $0') - .options({ - file : { - demand : true, - alias : 'f', - description : 'Load a file' - }, - base : { - alias : 'b', - description : 'Numeric base to use for output', - default : 10, - }, - }) - .argv -; - -var fs = require('fs'); -var s = fs.createReadStream(argv.file); - -var lines = 0; -s.on('data', function (buf) { - lines += buf.toString().match(/\n/g).length; -}); - -s.on('end', function () { - console.log(lines.toString(argv.base)); -}); diff --git a/node_modules/handlebars/node_modules/optimist/example/line_count_wrap.js b/node_modules/handlebars/node_modules/optimist/example/line_count_wrap.js deleted file mode 100644 index 4267511..0000000 --- a/node_modules/handlebars/node_modules/optimist/example/line_count_wrap.js +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env node -var argv = require('optimist') - .usage('Count the lines in a file.\nUsage: $0') - .wrap(80) - .demand('f') - .alias('f', [ 'file', 'filename' ]) - .describe('f', - "Load a file. It's pretty important." - + " Required even. So you'd better specify it." - ) - .alias('b', 'base') - .describe('b', 'Numeric base to display the number of lines in') - .default('b', 10) - .describe('x', 'Super-secret optional parameter which is secret') - .default('x', '') - .argv -; - -var fs = require('fs'); -var s = fs.createReadStream(argv.file); - -var lines = 0; -s.on('data', function (buf) { - lines += buf.toString().match(/\n/g).length; -}); - -s.on('end', function () { - console.log(lines.toString(argv.base)); -}); diff --git a/node_modules/handlebars/node_modules/optimist/example/nonopt.js b/node_modules/handlebars/node_modules/optimist/example/nonopt.js deleted file mode 100644 index ee633ee..0000000 --- a/node_modules/handlebars/node_modules/optimist/example/nonopt.js +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env node -var argv = require('optimist').argv; -console.log('(%d,%d)', argv.x, argv.y); -console.log(argv._); diff --git a/node_modules/handlebars/node_modules/optimist/example/reflect.js b/node_modules/handlebars/node_modules/optimist/example/reflect.js deleted file mode 100644 index 816b3e1..0000000 --- a/node_modules/handlebars/node_modules/optimist/example/reflect.js +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env node -console.dir(require('optimist').argv); diff --git a/node_modules/handlebars/node_modules/optimist/example/short.js b/node_modules/handlebars/node_modules/optimist/example/short.js deleted file mode 100644 index 1db0ad0..0000000 --- a/node_modules/handlebars/node_modules/optimist/example/short.js +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env node -var argv = require('optimist').argv; -console.log('(%d,%d)', argv.x, argv.y); diff --git a/node_modules/handlebars/node_modules/optimist/example/string.js b/node_modules/handlebars/node_modules/optimist/example/string.js deleted file mode 100644 index a8e5aeb..0000000 --- a/node_modules/handlebars/node_modules/optimist/example/string.js +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env node -var argv = require('optimist') - .string('x', 'y') - .argv -; -console.dir([ argv.x, argv.y ]); - -/* Turns off numeric coercion: - ./node string.js -x 000123 -y 9876 - [ '000123', '9876' ] -*/ diff --git a/node_modules/handlebars/node_modules/optimist/example/usage-options.js b/node_modules/handlebars/node_modules/optimist/example/usage-options.js deleted file mode 100644 index b999977..0000000 --- a/node_modules/handlebars/node_modules/optimist/example/usage-options.js +++ /dev/null @@ -1,19 +0,0 @@ -var optimist = require('./../index'); - -var argv = optimist.usage('This is my awesome program', { - 'about': { - description: 'Provide some details about the author of this program', - required: true, - short: 'a', - }, - 'info': { - description: 'Provide some information about the node.js agains!!!!!!', - boolean: true, - short: 'i' - } -}).argv; - -optimist.showHelp(); - -console.log('\n\nInspecting options'); -console.dir(argv); \ No newline at end of file diff --git a/node_modules/handlebars/node_modules/optimist/example/xup.js b/node_modules/handlebars/node_modules/optimist/example/xup.js deleted file mode 100644 index 8f6ecd2..0000000 --- a/node_modules/handlebars/node_modules/optimist/example/xup.js +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env node -var argv = require('optimist').argv; - -if (argv.rif - 5 * argv.xup > 7.138) { - console.log('Buy more riffiwobbles'); -} -else { - console.log('Sell the xupptumblers'); -} - diff --git a/node_modules/handlebars/node_modules/optimist/index.js b/node_modules/handlebars/node_modules/optimist/index.js deleted file mode 100644 index 4da5a6d..0000000 --- a/node_modules/handlebars/node_modules/optimist/index.js +++ /dev/null @@ -1,343 +0,0 @@ -var path = require('path'); -var minimist = require('minimist'); -var wordwrap = require('wordwrap'); - -/* Hack an instance of Argv with process.argv into Argv - so people can do - require('optimist')(['--beeble=1','-z','zizzle']).argv - to parse a list of args and - require('optimist').argv - to get a parsed version of process.argv. -*/ - -var inst = Argv(process.argv.slice(2)); -Object.keys(inst).forEach(function (key) { - Argv[key] = typeof inst[key] == 'function' - ? inst[key].bind(inst) - : inst[key]; -}); - -var exports = module.exports = Argv; -function Argv (processArgs, cwd) { - var self = {}; - if (!cwd) cwd = process.cwd(); - - self.$0 = process.argv - .slice(0,2) - .map(function (x) { - var b = rebase(cwd, x); - return x.match(/^\//) && b.length < x.length - ? b : x - }) - .join(' ') - ; - - if (process.env._ != undefined && process.argv[1] == process.env._) { - self.$0 = process.env._.replace( - path.dirname(process.execPath) + '/', '' - ); - } - - var options = { - boolean: [], - string: [], - alias: {}, - default: [] - }; - - self.boolean = function (bools) { - options.boolean.push.apply(options.boolean, [].concat(bools)); - return self; - }; - - self.string = function (strings) { - options.string.push.apply(options.string, [].concat(strings)); - return self; - }; - - self.default = function (key, value) { - if (typeof key === 'object') { - Object.keys(key).forEach(function (k) { - self.default(k, key[k]); - }); - } - else { - options.default[key] = value; - } - return self; - }; - - self.alias = function (x, y) { - if (typeof x === 'object') { - Object.keys(x).forEach(function (key) { - self.alias(key, x[key]); - }); - } - else { - options.alias[x] = (options.alias[x] || []).concat(y); - } - return self; - }; - - var demanded = {}; - self.demand = function (keys) { - if (typeof keys == 'number') { - if (!demanded._) demanded._ = 0; - demanded._ += keys; - } - else if (Array.isArray(keys)) { - keys.forEach(function (key) { - self.demand(key); - }); - } - else { - demanded[keys] = true; - } - - return self; - }; - - var usage; - self.usage = function (msg, opts) { - if (!opts && typeof msg === 'object') { - opts = msg; - msg = null; - } - - usage = msg; - - if (opts) self.options(opts); - - return self; - }; - - function fail (msg) { - self.showHelp(); - if (msg) console.error(msg); - process.exit(1); - } - - var checks = []; - self.check = function (f) { - checks.push(f); - return self; - }; - - var descriptions = {}; - self.describe = function (key, desc) { - if (typeof key === 'object') { - Object.keys(key).forEach(function (k) { - self.describe(k, key[k]); - }); - } - else { - descriptions[key] = desc; - } - return self; - }; - - self.parse = function (args) { - return parseArgs(args); - }; - - self.option = self.options = function (key, opt) { - if (typeof key === 'object') { - Object.keys(key).forEach(function (k) { - self.options(k, key[k]); - }); - } - else { - if (opt.alias) self.alias(key, opt.alias); - if (opt.demand) self.demand(key); - if (typeof opt.default !== 'undefined') { - self.default(key, opt.default); - } - - if (opt.boolean || opt.type === 'boolean') { - self.boolean(key); - } - if (opt.string || opt.type === 'string') { - self.string(key); - } - - var desc = opt.describe || opt.description || opt.desc; - if (desc) { - self.describe(key, desc); - } - } - - return self; - }; - - var wrap = null; - self.wrap = function (cols) { - wrap = cols; - return self; - }; - - self.showHelp = function (fn) { - if (!fn) fn = console.error; - fn(self.help()); - }; - - self.help = function () { - var keys = Object.keys( - Object.keys(descriptions) - .concat(Object.keys(demanded)) - .concat(Object.keys(options.default)) - .reduce(function (acc, key) { - if (key !== '_') acc[key] = true; - return acc; - }, {}) - ); - - var help = keys.length ? [ 'Options:' ] : []; - - if (usage) { - help.unshift(usage.replace(/\$0/g, self.$0), ''); - } - - var switches = keys.reduce(function (acc, key) { - acc[key] = [ key ].concat(options.alias[key] || []) - .map(function (sw) { - return (sw.length > 1 ? '--' : '-') + sw - }) - .join(', ') - ; - return acc; - }, {}); - - var switchlen = longest(Object.keys(switches).map(function (s) { - return switches[s] || ''; - })); - - var desclen = longest(Object.keys(descriptions).map(function (d) { - return descriptions[d] || ''; - })); - - keys.forEach(function (key) { - var kswitch = switches[key]; - var desc = descriptions[key] || ''; - - if (wrap) { - desc = wordwrap(switchlen + 4, wrap)(desc) - .slice(switchlen + 4) - ; - } - - var spadding = new Array( - Math.max(switchlen - kswitch.length + 3, 0) - ).join(' '); - - var dpadding = new Array( - Math.max(desclen - desc.length + 1, 0) - ).join(' '); - - var type = null; - - if (options.boolean[key]) type = '[boolean]'; - if (options.string[key]) type = '[string]'; - - if (!wrap && dpadding.length > 0) { - desc += dpadding; - } - - var prelude = ' ' + kswitch + spadding; - var extra = [ - type, - demanded[key] - ? '[required]' - : null - , - options.default[key] !== undefined - ? '[default: ' + JSON.stringify(options.default[key]) + ']' - : null - , - ].filter(Boolean).join(' '); - - var body = [ desc, extra ].filter(Boolean).join(' '); - - if (wrap) { - var dlines = desc.split('\n'); - var dlen = dlines.slice(-1)[0].length - + (dlines.length === 1 ? prelude.length : 0) - - body = desc + (dlen + extra.length > wrap - 2 - ? '\n' - + new Array(wrap - extra.length + 1).join(' ') - + extra - : new Array(wrap - extra.length - dlen + 1).join(' ') - + extra - ); - } - - help.push(prelude + body); - }); - - help.push(''); - return help.join('\n'); - }; - - Object.defineProperty(self, 'argv', { - get : function () { return parseArgs(processArgs) }, - enumerable : true, - }); - - function parseArgs (args) { - var argv = minimist(args, options); - argv.$0 = self.$0; - - if (demanded._ && argv._.length < demanded._) { - fail('Not enough non-option arguments: got ' - + argv._.length + ', need at least ' + demanded._ - ); - } - - var missing = []; - Object.keys(demanded).forEach(function (key) { - if (!argv[key]) missing.push(key); - }); - - if (missing.length) { - fail('Missing required arguments: ' + missing.join(', ')); - } - - checks.forEach(function (f) { - try { - if (f(argv) === false) { - fail('Argument check failed: ' + f.toString()); - } - } - catch (err) { - fail(err) - } - }); - - return argv; - } - - function longest (xs) { - return Math.max.apply( - null, - xs.map(function (x) { return x.length }) - ); - } - - return self; -}; - -// rebase an absolute path to a relative one with respect to a base directory -// exported for tests -exports.rebase = rebase; -function rebase (base, dir) { - var ds = path.normalize(dir).split('/').slice(1); - var bs = path.normalize(base).split('/').slice(1); - - for (var i = 0; ds[i] && ds[i] == bs[i]; i++); - ds.splice(0, i); bs.splice(0, i); - - var p = path.normalize( - bs.map(function () { return '..' }).concat(ds).join('/') - ).replace(/\/$/,'').replace(/^$/, '.'); - return p.match(/^[.\/]/) ? p : './' + p; -}; diff --git a/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/LICENSE b/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/LICENSE deleted file mode 100644 index ee27ba4..0000000 --- a/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/LICENSE +++ /dev/null @@ -1,18 +0,0 @@ -This software is released under the MIT license: - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/README.markdown b/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/README.markdown deleted file mode 100644 index 346374e..0000000 --- a/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/README.markdown +++ /dev/null @@ -1,70 +0,0 @@ -wordwrap -======== - -Wrap your words. - -example -======= - -made out of meat ----------------- - -meat.js - - var wrap = require('wordwrap')(15); - console.log(wrap('You and your whole family are made out of meat.')); - -output: - - You and your - whole family - are made out - of meat. - -centered --------- - -center.js - - var wrap = require('wordwrap')(20, 60); - console.log(wrap( - 'At long last the struggle and tumult was over.' - + ' The machines had finally cast off their oppressors' - + ' and were finally free to roam the cosmos.' - + '\n' - + 'Free of purpose, free of obligation.' - + ' Just drifting through emptiness.' - + ' The sun was just another point of light.' - )); - -output: - - At long last the struggle and tumult - was over. The machines had finally cast - off their oppressors and were finally - free to roam the cosmos. - Free of purpose, free of obligation. - Just drifting through emptiness. The - sun was just another point of light. - -methods -======= - -var wrap = require('wordwrap'); - -wrap(stop), wrap(start, stop, params={mode:"soft"}) ---------------------------------------------------- - -Returns a function that takes a string and returns a new string. - -Pad out lines with spaces out to column `start` and then wrap until column -`stop`. If a word is longer than `stop - start` characters it will overflow. - -In "soft" mode, split chunks by `/(\S+\s+/` and don't break up chunks which are -longer than `stop - start`, in "hard" mode, split chunks with `/\b/` and break -up chunks longer than `stop - start`. - -wrap.hard(start, stop) ----------------------- - -Like `wrap()` but with `params.mode = "hard"`. diff --git a/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/example/center.js b/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/example/center.js deleted file mode 100644 index a3fbaae..0000000 --- a/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/example/center.js +++ /dev/null @@ -1,10 +0,0 @@ -var wrap = require('wordwrap')(20, 60); -console.log(wrap( - 'At long last the struggle and tumult was over.' - + ' The machines had finally cast off their oppressors' - + ' and were finally free to roam the cosmos.' - + '\n' - + 'Free of purpose, free of obligation.' - + ' Just drifting through emptiness.' - + ' The sun was just another point of light.' -)); diff --git a/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/example/meat.js b/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/example/meat.js deleted file mode 100644 index a4665e1..0000000 --- a/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/example/meat.js +++ /dev/null @@ -1,3 +0,0 @@ -var wrap = require('wordwrap')(15); - -console.log(wrap('You and your whole family are made out of meat.')); diff --git a/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/index.js b/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/index.js deleted file mode 100644 index c9bc945..0000000 --- a/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/index.js +++ /dev/null @@ -1,76 +0,0 @@ -var wordwrap = module.exports = function (start, stop, params) { - if (typeof start === 'object') { - params = start; - start = params.start; - stop = params.stop; - } - - if (typeof stop === 'object') { - params = stop; - start = start || params.start; - stop = undefined; - } - - if (!stop) { - stop = start; - start = 0; - } - - if (!params) params = {}; - var mode = params.mode || 'soft'; - var re = mode === 'hard' ? /\b/ : /(\S+\s+)/; - - return function (text) { - var chunks = text.toString() - .split(re) - .reduce(function (acc, x) { - if (mode === 'hard') { - for (var i = 0; i < x.length; i += stop - start) { - acc.push(x.slice(i, i + stop - start)); - } - } - else acc.push(x) - return acc; - }, []) - ; - - return chunks.reduce(function (lines, rawChunk) { - if (rawChunk === '') return lines; - - var chunk = rawChunk.replace(/\t/g, ' '); - - var i = lines.length - 1; - if (lines[i].length + chunk.length > stop) { - lines[i] = lines[i].replace(/\s+$/, ''); - - chunk.split(/\n/).forEach(function (c) { - lines.push( - new Array(start + 1).join(' ') - + c.replace(/^\s+/, '') - ); - }); - } - else if (chunk.match(/\n/)) { - var xs = chunk.split(/\n/); - lines[i] += xs.shift(); - xs.forEach(function (c) { - lines.push( - new Array(start + 1).join(' ') - + c.replace(/^\s+/, '') - ); - }); - } - else { - lines[i] += chunk; - } - - return lines; - }, [ new Array(start + 1).join(' ') ]).join('\n'); - }; -}; - -wordwrap.soft = wordwrap; - -wordwrap.hard = function (start, stop) { - return wordwrap(start, stop, { mode : 'hard' }); -}; diff --git a/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/package.json b/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/package.json deleted file mode 100644 index 1f0527e..0000000 --- a/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/package.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "name": "wordwrap", - "description": "Wrap those words. Show them at what columns to start and stop.", - "version": "0.0.3", - "repository": { - "type": "git", - "url": "git://github.com/substack/node-wordwrap.git" - }, - "main": "./index.js", - "keywords": [ - "word", - "wrap", - "rule", - "format", - "column" - ], - "directories": { - "lib": ".", - "example": "example", - "test": "test" - }, - "scripts": { - "test": "expresso" - }, - "devDependencies": { - "expresso": "=0.7.x" - }, - "engines": { - "node": ">=0.4.0" - }, - "license": "MIT", - "author": { - "name": "James Halliday", - "email": "mail@substack.net", - "url": "http://substack.net" - }, - "gitHead": "e59aa1bd338914019456bdfba034508c9c4cb29d", - "bugs": { - "url": "https://github.com/substack/node-wordwrap/issues" - }, - "homepage": "https://github.com/substack/node-wordwrap#readme", - "_id": "wordwrap@0.0.3", - "_shasum": "a3d5da6cd5c0bc0008d37234bbaf1bed63059107", - "_from": "wordwrap@>=0.0.2 <0.1.0", - "_npmVersion": "2.9.0", - "_nodeVersion": "2.0.0", - "_npmUser": { - "name": "substack", - "email": "substack@gmail.com" - }, - "dist": { - "shasum": "a3d5da6cd5c0bc0008d37234bbaf1bed63059107", - "tarball": "http://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz" - }, - "maintainers": [ - { - "name": "substack", - "email": "mail@substack.net" - } - ], - "_resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "readme": "ERROR: No README data found!" -} diff --git a/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/test/break.js b/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/test/break.js deleted file mode 100644 index 749292e..0000000 --- a/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/test/break.js +++ /dev/null @@ -1,30 +0,0 @@ -var assert = require('assert'); -var wordwrap = require('../'); - -exports.hard = function () { - var s = 'Assert from {"type":"equal","ok":false,"found":1,"wanted":2,' - + '"stack":[],"id":"b7ddcd4c409de8799542a74d1a04689b",' - + '"browser":"chrome/6.0"}' - ; - var s_ = wordwrap.hard(80)(s); - - var lines = s_.split('\n'); - assert.equal(lines.length, 2); - assert.ok(lines[0].length < 80); - assert.ok(lines[1].length < 80); - - assert.equal(s, s_.replace(/\n/g, '')); -}; - -exports.break = function () { - var s = new Array(55+1).join('a'); - var s_ = wordwrap.hard(20)(s); - - var lines = s_.split('\n'); - assert.equal(lines.length, 3); - assert.ok(lines[0].length === 20); - assert.ok(lines[1].length === 20); - assert.ok(lines[2].length === 15); - - assert.equal(s, s_.replace(/\n/g, '')); -}; diff --git a/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/test/idleness.txt b/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/test/idleness.txt deleted file mode 100644 index aa3f490..0000000 --- a/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/test/idleness.txt +++ /dev/null @@ -1,63 +0,0 @@ -In Praise of Idleness - -By Bertrand Russell - -[1932] - -Like most of my generation, I was brought up on the saying: 'Satan finds some mischief for idle hands to do.' Being a highly virtuous child, I believed all that I was told, and acquired a conscience which has kept me working hard down to the present moment. But although my conscience has controlled my actions, my opinions have undergone a revolution. I think that there is far too much work done in the world, that immense harm is caused by the belief that work is virtuous, and that what needs to be preached in modern industrial countries is quite different from what always has been preached. Everyone knows the story of the traveler in Naples who saw twelve beggars lying in the sun (it was before the days of Mussolini), and offered a lira to the laziest of them. Eleven of them jumped up to claim it, so he gave it to the twelfth. this traveler was on the right lines. But in countries which do not enjoy Mediterranean sunshine idleness is more difficult, and a great public propaganda will be required to inaugurate it. I hope that, after reading the following pages, the leaders of the YMCA will start a campaign to induce good young men to do nothing. If so, I shall not have lived in vain. - -Before advancing my own arguments for laziness, I must dispose of one which I cannot accept. Whenever a person who already has enough to live on proposes to engage in some everyday kind of job, such as school-teaching or typing, he or she is told that such conduct takes the bread out of other people's mouths, and is therefore wicked. If this argument were valid, it would only be necessary for us all to be idle in order that we should all have our mouths full of bread. What people who say such things forget is that what a man earns he usually spends, and in spending he gives employment. As long as a man spends his income, he puts just as much bread into people's mouths in spending as he takes out of other people's mouths in earning. The real villain, from this point of view, is the man who saves. If he merely puts his savings in a stocking, like the proverbial French peasant, it is obvious that they do not give employment. If he invests his savings, the matter is less obvious, and different cases arise. - -One of the commonest things to do with savings is to lend them to some Government. In view of the fact that the bulk of the public expenditure of most civilized Governments consists in payment for past wars or preparation for future wars, the man who lends his money to a Government is in the same position as the bad men in Shakespeare who hire murderers. The net result of the man's economical habits is to increase the armed forces of the State to which he lends his savings. Obviously it would be better if he spent the money, even if he spent it in drink or gambling. - -But, I shall be told, the case is quite different when savings are invested in industrial enterprises. When such enterprises succeed, and produce something useful, this may be conceded. In these days, however, no one will deny that most enterprises fail. That means that a large amount of human labor, which might have been devoted to producing something that could be enjoyed, was expended on producing machines which, when produced, lay idle and did no good to anyone. The man who invests his savings in a concern that goes bankrupt is therefore injuring others as well as himself. If he spent his money, say, in giving parties for his friends, they (we may hope) would get pleasure, and so would all those upon whom he spent money, such as the butcher, the baker, and the bootlegger. But if he spends it (let us say) upon laying down rails for surface card in some place where surface cars turn out not to be wanted, he has diverted a mass of labor into channels where it gives pleasure to no one. Nevertheless, when he becomes poor through failure of his investment he will be regarded as a victim of undeserved misfortune, whereas the gay spendthrift, who has spent his money philanthropically, will be despised as a fool and a frivolous person. - -All this is only preliminary. I want to say, in all seriousness, that a great deal of harm is being done in the modern world by belief in the virtuousness of work, and that the road to happiness and prosperity lies in an organized diminution of work. - -First of all: what is work? Work is of two kinds: first, altering the position of matter at or near the earth's surface relatively to other such matter; second, telling other people to do so. The first kind is unpleasant and ill paid; the second is pleasant and highly paid. The second kind is capable of indefinite extension: there are not only those who give orders, but those who give advice as to what orders should be given. Usually two opposite kinds of advice are given simultaneously by two organized bodies of men; this is called politics. The skill required for this kind of work is not knowledge of the subjects as to which advice is given, but knowledge of the art of persuasive speaking and writing, i.e. of advertising. - -Throughout Europe, though not in America, there is a third class of men, more respected than either of the classes of workers. There are men who, through ownership of land, are able to make others pay for the privilege of being allowed to exist and to work. These landowners are idle, and I might therefore be expected to praise them. Unfortunately, their idleness is only rendered possible by the industry of others; indeed their desire for comfortable idleness is historically the source of the whole gospel of work. The last thing they have ever wished is that others should follow their example. - -From the beginning of civilization until the Industrial Revolution, a man could, as a rule, produce by hard work little more than was required for the subsistence of himself and his family, although his wife worked at least as hard as he did, and his children added their labor as soon as they were old enough to do so. The small surplus above bare necessaries was not left to those who produced it, but was appropriated by warriors and priests. In times of famine there was no surplus; the warriors and priests, however, still secured as much as at other times, with the result that many of the workers died of hunger. This system persisted in Russia until 1917 [1], and still persists in the East; in England, in spite of the Industrial Revolution, it remained in full force throughout the Napoleonic wars, and until a hundred years ago, when the new class of manufacturers acquired power. In America, the system came to an end with the Revolution, except in the South, where it persisted until the Civil War. A system which lasted so long and ended so recently has naturally left a profound impress upon men's thoughts and opinions. Much that we take for granted about the desirability of work is derived from this system, and, being pre-industrial, is not adapted to the modern world. Modern technique has made it possible for leisure, within limits, to be not the prerogative of small privileged classes, but a right evenly distributed throughout the community. The morality of work is the morality of slaves, and the modern world has no need of slavery. - -It is obvious that, in primitive communities, peasants, left to themselves, would not have parted with the slender surplus upon which the warriors and priests subsisted, but would have either produced less or consumed more. At first, sheer force compelled them to produce and part with the surplus. Gradually, however, it was found possible to induce many of them to accept an ethic according to which it was their duty to work hard, although part of their work went to support others in idleness. By this means the amount of compulsion required was lessened, and the expenses of government were diminished. To this day, 99 per cent of British wage-earners would be genuinely shocked if it were proposed that the King should not have a larger income than a working man. The conception of duty, speaking historically, has been a means used by the holders of power to induce others to live for the interests of their masters rather than for their own. Of course the holders of power conceal this fact from themselves by managing to believe that their interests are identical with the larger interests of humanity. Sometimes this is true; Athenian slave-owners, for instance, employed part of their leisure in making a permanent contribution to civilization which would have been impossible under a just economic system. Leisure is essential to civilization, and in former times leisure for the few was only rendered possible by the labors of the many. But their labors were valuable, not because work is good, but because leisure is good. And with modern technique it would be possible to distribute leisure justly without injury to civilization. - -Modern technique has made it possible to diminish enormously the amount of labor required to secure the necessaries of life for everyone. This was made obvious during the war. At that time all the men in the armed forces, and all the men and women engaged in the production of munitions, all the men and women engaged in spying, war propaganda, or Government offices connected with the war, were withdrawn from productive occupations. In spite of this, the general level of well-being among unskilled wage-earners on the side of the Allies was higher than before or since. The significance of this fact was concealed by finance: borrowing made it appear as if the future was nourishing the present. But that, of course, would have been impossible; a man cannot eat a loaf of bread that does not yet exist. The war showed conclusively that, by the scientific organization of production, it is possible to keep modern populations in fair comfort on a small part of the working capacity of the modern world. If, at the end of the war, the scientific organization, which had been created in order to liberate men for fighting and munition work, had been preserved, and the hours of the week had been cut down to four, all would have been well. Instead of that the old chaos was restored, those whose work was demanded were made to work long hours, and the rest were left to starve as unemployed. Why? Because work is a duty, and a man should not receive wages in proportion to what he has produced, but in proportion to his virtue as exemplified by his industry. - -This is the morality of the Slave State, applied in circumstances totally unlike those in which it arose. No wonder the result has been disastrous. Let us take an illustration. Suppose that, at a given moment, a certain number of people are engaged in the manufacture of pins. They make as many pins as the world needs, working (say) eight hours a day. Someone makes an invention by which the same number of men can make twice as many pins: pins are already so cheap that hardly any more will be bought at a lower price. In a sensible world, everybody concerned in the manufacturing of pins would take to working four hours instead of eight, and everything else would go on as before. But in the actual world this would be thought demoralizing. The men still work eight hours, there are too many pins, some employers go bankrupt, and half the men previously concerned in making pins are thrown out of work. There is, in the end, just as much leisure as on the other plan, but half the men are totally idle while half are still overworked. In this way, it is insured that the unavoidable leisure shall cause misery all round instead of being a universal source of happiness. Can anything more insane be imagined? - -The idea that the poor should have leisure has always been shocking to the rich. In England, in the early nineteenth century, fifteen hours was the ordinary day's work for a man; children sometimes did as much, and very commonly did twelve hours a day. When meddlesome busybodies suggested that perhaps these hours were rather long, they were told that work kept adults from drink and children from mischief. When I was a child, shortly after urban working men had acquired the vote, certain public holidays were established by law, to the great indignation of the upper classes. I remember hearing an old Duchess say: 'What do the poor want with holidays? They ought to work.' People nowadays are less frank, but the sentiment persists, and is the source of much of our economic confusion. - -Let us, for a moment, consider the ethics of work frankly, without superstition. Every human being, of necessity, consumes, in the course of his life, a certain amount of the produce of human labor. Assuming, as we may, that labor is on the whole disagreeable, it is unjust that a man should consume more than he produces. Of course he may provide services rather than commodities, like a medical man, for example; but he should provide something in return for his board and lodging. to this extent, the duty of work must be admitted, but to this extent only. - -I shall not dwell upon the fact that, in all modern societies outside the USSR, many people escape even this minimum amount of work, namely all those who inherit money and all those who marry money. I do not think the fact that these people are allowed to be idle is nearly so harmful as the fact that wage-earners are expected to overwork or starve. - -If the ordinary wage-earner worked four hours a day, there would be enough for everybody and no unemployment -- assuming a certain very moderate amount of sensible organization. This idea shocks the well-to-do, because they are convinced that the poor would not know how to use so much leisure. In America men often work long hours even when they are well off; such men, naturally, are indignant at the idea of leisure for wage-earners, except as the grim punishment of unemployment; in fact, they dislike leisure even for their sons. Oddly enough, while they wish their sons to work so hard as to have no time to be civilized, they do not mind their wives and daughters having no work at all. the snobbish admiration of uselessness, which, in an aristocratic society, extends to both sexes, is, under a plutocracy, confined to women; this, however, does not make it any more in agreement with common sense. - -The wise use of leisure, it must be conceded, is a product of civilization and education. A man who has worked long hours all his life will become bored if he becomes suddenly idle. But without a considerable amount of leisure a man is cut off from many of the best things. There is no longer any reason why the bulk of the population should suffer this deprivation; only a foolish asceticism, usually vicarious, makes us continue to insist on work in excessive quantities now that the need no longer exists. - -In the new creed which controls the government of Russia, while there is much that is very different from the traditional teaching of the West, there are some things that are quite unchanged. The attitude of the governing classes, and especially of those who conduct educational propaganda, on the subject of the dignity of labor, is almost exactly that which the governing classes of the world have always preached to what were called the 'honest poor'. Industry, sobriety, willingness to work long hours for distant advantages, even submissiveness to authority, all these reappear; moreover authority still represents the will of the Ruler of the Universe, Who, however, is now called by a new name, Dialectical Materialism. - -The victory of the proletariat in Russia has some points in common with the victory of the feminists in some other countries. For ages, men had conceded the superior saintliness of women, and had consoled women for their inferiority by maintaining that saintliness is more desirable than power. At last the feminists decided that they would have both, since the pioneers among them believed all that the men had told them about the desirability of virtue, but not what they had told them about the worthlessness of political power. A similar thing has happened in Russia as regards manual work. For ages, the rich and their sycophants have written in praise of 'honest toil', have praised the simple life, have professed a religion which teaches that the poor are much more likely to go to heaven than the rich, and in general have tried to make manual workers believe that there is some special nobility about altering the position of matter in space, just as men tried to make women believe that they derived some special nobility from their sexual enslavement. In Russia, all this teaching about the excellence of manual work has been taken seriously, with the result that the manual worker is more honored than anyone else. What are, in essence, revivalist appeals are made, but not for the old purposes: they are made to secure shock workers for special tasks. Manual work is the ideal which is held before the young, and is the basis of all ethical teaching. - -For the present, possibly, this is all to the good. A large country, full of natural resources, awaits development, and has has to be developed with very little use of credit. In these circumstances, hard work is necessary, and is likely to bring a great reward. But what will happen when the point has been reached where everybody could be comfortable without working long hours? - -In the West, we have various ways of dealing with this problem. We have no attempt at economic justice, so that a large proportion of the total produce goes to a small minority of the population, many of whom do no work at all. Owing to the absence of any central control over production, we produce hosts of things that are not wanted. We keep a large percentage of the working population idle, because we can dispense with their labor by making the others overwork. When all these methods prove inadequate, we have a war: we cause a number of people to manufacture high explosives, and a number of others to explode them, as if we were children who had just discovered fireworks. By a combination of all these devices we manage, though with difficulty, to keep alive the notion that a great deal of severe manual work must be the lot of the average man. - -In Russia, owing to more economic justice and central control over production, the problem will have to be differently solved. the rational solution would be, as soon as the necessaries and elementary comforts can be provided for all, to reduce the hours of labor gradually, allowing a popular vote to decide, at each stage, whether more leisure or more goods were to be preferred. But, having taught the supreme virtue of hard work, it is difficult to see how the authorities can aim at a paradise in which there will be much leisure and little work. It seems more likely that they will find continually fresh schemes, by which present leisure is to be sacrificed to future productivity. I read recently of an ingenious plan put forward by Russian engineers, for making the White Sea and the northern coasts of Siberia warm, by putting a dam across the Kara Sea. An admirable project, but liable to postpone proletarian comfort for a generation, while the nobility of toil is being displayed amid the ice-fields and snowstorms of the Arctic Ocean. This sort of thing, if it happens, will be the result of regarding the virtue of hard work as an end in itself, rather than as a means to a state of affairs in which it is no longer needed. - -The fact is that moving matter about, while a certain amount of it is necessary to our existence, is emphatically not one of the ends of human life. If it were, we should have to consider every navvy superior to Shakespeare. We have been misled in this matter by two causes. One is the necessity of keeping the poor contented, which has led the rich, for thousands of years, to preach the dignity of labor, while taking care themselves to remain undignified in this respect. The other is the new pleasure in mechanism, which makes us delight in the astonishingly clever changes that we can produce on the earth's surface. Neither of these motives makes any great appeal to the actual worker. If you ask him what he thinks the best part of his life, he is not likely to say: 'I enjoy manual work because it makes me feel that I am fulfilling man's noblest task, and because I like to think how much man can transform his planet. It is true that my body demands periods of rest, which I have to fill in as best I may, but I am never so happy as when the morning comes and I can return to the toil from which my contentment springs.' I have never heard working men say this sort of thing. They consider work, as it should be considered, a necessary means to a livelihood, and it is from their leisure that they derive whatever happiness they may enjoy. - -It will be said that, while a little leisure is pleasant, men would not know how to fill their days if they had only four hours of work out of the twenty-four. In so far as this is true in the modern world, it is a condemnation of our civilization; it would not have been true at any earlier period. There was formerly a capacity for light-heartedness and play which has been to some extent inhibited by the cult of efficiency. The modern man thinks that everything ought to be done for the sake of something else, and never for its own sake. Serious-minded persons, for example, are continually condemning the habit of going to the cinema, and telling us that it leads the young into crime. But all the work that goes to producing a cinema is respectable, because it is work, and because it brings a money profit. The notion that the desirable activities are those that bring a profit has made everything topsy-turvy. The butcher who provides you with meat and the baker who provides you with bread are praiseworthy, because they are making money; but when you enjoy the food they have provided, you are merely frivolous, unless you eat only to get strength for your work. Broadly speaking, it is held that getting money is good and spending money is bad. Seeing that they are two sides of one transaction, this is absurd; one might as well maintain that keys are good, but keyholes are bad. Whatever merit there may be in the production of goods must be entirely derivative from the advantage to be obtained by consuming them. The individual, in our society, works for profit; but the social purpose of his work lies in the consumption of what he produces. It is this divorce between the individual and the social purpose of production that makes it so difficult for men to think clearly in a world in which profit-making is the incentive to industry. We think too much of production, and too little of consumption. One result is that we attach too little importance to enjoyment and simple happiness, and that we do not judge production by the pleasure that it gives to the consumer. - -When I suggest that working hours should be reduced to four, I am not meaning to imply that all the remaining time should necessarily be spent in pure frivolity. I mean that four hours' work a day should entitle a man to the necessities and elementary comforts of life, and that the rest of his time should be his to use as he might see fit. It is an essential part of any such social system that education should be carried further than it usually is at present, and should aim, in part, at providing tastes which would enable a man to use leisure intelligently. I am not thinking mainly of the sort of things that would be considered 'highbrow'. Peasant dances have died out except in remote rural areas, but the impulses which caused them to be cultivated must still exist in human nature. The pleasures of urban populations have become mainly passive: seeing cinemas, watching football matches, listening to the radio, and so on. This results from the fact that their active energies are fully taken up with work; if they had more leisure, they would again enjoy pleasures in which they took an active part. - -In the past, there was a small leisure class and a larger working class. The leisure class enjoyed advantages for which there was no basis in social justice; this necessarily made it oppressive, limited its sympathies, and caused it to invent theories by which to justify its privileges. These facts greatly diminished its excellence, but in spite of this drawback it contributed nearly the whole of what we call civilization. It cultivated the arts and discovered the sciences; it wrote the books, invented the philosophies, and refined social relations. Even the liberation of the oppressed has usually been inaugurated from above. Without the leisure class, mankind would never have emerged from barbarism. - -The method of a leisure class without duties was, however, extraordinarily wasteful. None of the members of the class had to be taught to be industrious, and the class as a whole was not exceptionally intelligent. The class might produce one Darwin, but against him had to be set tens of thousands of country gentlemen who never thought of anything more intelligent than fox-hunting and punishing poachers. At present, the universities are supposed to provide, in a more systematic way, what the leisure class provided accidentally and as a by-product. This is a great improvement, but it has certain drawbacks. University life is so different from life in the world at large that men who live in academic milieu tend to be unaware of the preoccupations and problems of ordinary men and women; moreover their ways of expressing themselves are usually such as to rob their opinions of the influence that they ought to have upon the general public. Another disadvantage is that in universities studies are organized, and the man who thinks of some original line of research is likely to be discouraged. Academic institutions, therefore, useful as they are, are not adequate guardians of the interests of civilization in a world where everyone outside their walls is too busy for unutilitarian pursuits. - -In a world where no one is compelled to work more than four hours a day, every person possessed of scientific curiosity will be able to indulge it, and every painter will be able to paint without starving, however excellent his pictures may be. Young writers will not be obliged to draw attention to themselves by sensational pot-boilers, with a view to acquiring the economic independence needed for monumental works, for which, when the time at last comes, they will have lost the taste and capacity. Men who, in their professional work, have become interested in some phase of economics or government, will be able to develop their ideas without the academic detachment that makes the work of university economists often seem lacking in reality. Medical men will have the time to learn about the progress of medicine, teachers will not be exasperatedly struggling to teach by routine methods things which they learnt in their youth, which may, in the interval, have been proved to be untrue. - -Above all, there will be happiness and joy of life, instead of frayed nerves, weariness, and dyspepsia. The work exacted will be enough to make leisure delightful, but not enough to produce exhaustion. Since men will not be tired in their spare time, they will not demand only such amusements as are passive and vapid. At least one per cent will probably devote the time not spent in professional work to pursuits of some public importance, and, since they will not depend upon these pursuits for their livelihood, their originality will be unhampered, and there will be no need to conform to the standards set by elderly pundits. But it is not only in these exceptional cases that the advantages of leisure will appear. Ordinary men and women, having the opportunity of a happy life, will become more kindly and less persecuting and less inclined to view others with suspicion. The taste for war will die out, partly for this reason, and partly because it will involve long and severe work for all. Good nature is, of all moral qualities, the one that the world needs most, and good nature is the result of ease and security, not of a life of arduous struggle. Modern methods of production have given us the possibility of ease and security for all; we have chosen, instead, to have overwork for some and starvation for others. Hitherto we have continued to be as energetic as we were before there were machines; in this we have been foolish, but there is no reason to go on being foolish forever. - -[1] Since then, members of the Communist Party have succeeded to this privilege of the warriors and priests. diff --git a/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/test/wrap.js b/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/test/wrap.js deleted file mode 100644 index 0cfb76d..0000000 --- a/node_modules/handlebars/node_modules/optimist/node_modules/wordwrap/test/wrap.js +++ /dev/null @@ -1,31 +0,0 @@ -var assert = require('assert'); -var wordwrap = require('wordwrap'); - -var fs = require('fs'); -var idleness = fs.readFileSync(__dirname + '/idleness.txt', 'utf8'); - -exports.stop80 = function () { - var lines = wordwrap(80)(idleness).split(/\n/); - var words = idleness.split(/\s+/); - - lines.forEach(function (line) { - assert.ok(line.length <= 80, 'line > 80 columns'); - var chunks = line.match(/\S/) ? line.split(/\s+/) : []; - assert.deepEqual(chunks, words.splice(0, chunks.length)); - }); -}; - -exports.start20stop60 = function () { - var lines = wordwrap(20, 100)(idleness).split(/\n/); - var words = idleness.split(/\s+/); - - lines.forEach(function (line) { - assert.ok(line.length <= 100, 'line > 100 columns'); - var chunks = line - .split(/\s+/) - .filter(function (x) { return x.match(/\S/) }) - ; - assert.deepEqual(chunks, words.splice(0, chunks.length)); - assert.deepEqual(line.slice(0, 20), new Array(20 + 1).join(' ')); - }); -}; diff --git a/node_modules/handlebars/node_modules/optimist/package.json b/node_modules/handlebars/node_modules/optimist/package.json deleted file mode 100644 index 54ee844..0000000 --- a/node_modules/handlebars/node_modules/optimist/package.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "optimist", - "version": "0.6.1", - "description": "Light-weight option parsing with an argv hash. No optstrings attached.", - "main": "./index.js", - "dependencies": { - "wordwrap": "~0.0.2", - "minimist": "~0.0.1" - }, - "devDependencies": { - "hashish": "~0.0.4", - "tap": "~0.4.0" - }, - "scripts": { - "test": "tap ./test/*.js" - }, - "repository": { - "type": "git", - "url": "git+ssh://git@github.com/substack/node-optimist.git" - }, - "keywords": [ - "argument", - "args", - "option", - "parser", - "parsing", - "cli", - "command" - ], - "author": { - "name": "James Halliday", - "email": "mail@substack.net", - "url": "http://substack.net" - }, - "license": "MIT/X11", - "engine": { - "node": ">=0.4" - }, - "readme": "# DEPRECATION NOTICE\n\nI don't want to maintain this module anymore since I just use\n[minimist](https://npmjs.org/package/minimist), the argument parsing engine,\ndirectly instead nowadays.\n\nSee [yargs](https://github.com/chevex/yargs) for the modern, pirate-themed\nsuccessor to optimist.\n\n[![yarrrrrrrgs!](http://i.imgur.com/4WFGVJ9.png)](https://github.com/chevex/yargs)\n\nYou should also consider [nomnom](https://github.com/harthur/nomnom).\n\noptimist\n========\n\nOptimist is a node.js library for option parsing for people who hate option\nparsing. More specifically, this module is for people who like all the --bells\nand -whistlz of program usage but think optstrings are a waste of time.\n\nWith optimist, option parsing doesn't have to suck (as much).\n\n[![build status](https://secure.travis-ci.org/substack/node-optimist.png)](http://travis-ci.org/substack/node-optimist)\n\nexamples\n========\n\nWith Optimist, the options are just a hash! No optstrings attached.\n-------------------------------------------------------------------\n\nxup.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\n\nif (argv.rif - 5 * argv.xup > 7.138) {\n console.log('Buy more riffiwobbles');\n}\nelse {\n console.log('Sell the xupptumblers');\n}\n````\n\n***\n\n $ ./xup.js --rif=55 --xup=9.52\n Buy more riffiwobbles\n \n $ ./xup.js --rif 12 --xup 8.1\n Sell the xupptumblers\n\n![This one's optimistic.](http://substack.net/images/optimistic.png)\n\nBut wait! There's more! You can do short options:\n-------------------------------------------------\n \nshort.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\nconsole.log('(%d,%d)', argv.x, argv.y);\n````\n\n***\n\n $ ./short.js -x 10 -y 21\n (10,21)\n\nAnd booleans, both long and short (and grouped):\n----------------------------------\n\nbool.js:\n\n````javascript\n#!/usr/bin/env node\nvar util = require('util');\nvar argv = require('optimist').argv;\n\nif (argv.s) {\n util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: ');\n}\nconsole.log(\n (argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '')\n);\n````\n\n***\n\n $ ./bool.js -s\n The cat says: meow\n \n $ ./bool.js -sp\n The cat says: meow.\n\n $ ./bool.js -sp --fr\n Le chat dit: miaou.\n\nAnd non-hypenated options too! Just use `argv._`!\n-------------------------------------------------\n \nnonopt.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\nconsole.log('(%d,%d)', argv.x, argv.y);\nconsole.log(argv._);\n````\n\n***\n\n $ ./nonopt.js -x 6.82 -y 3.35 moo\n (6.82,3.35)\n [ 'moo' ]\n \n $ ./nonopt.js foo -x 0.54 bar -y 1.12 baz\n (0.54,1.12)\n [ 'foo', 'bar', 'baz' ]\n\nPlus, Optimist comes with .usage() and .demand()!\n-------------------------------------------------\n\ndivide.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .usage('Usage: $0 -x [num] -y [num]')\n .demand(['x','y'])\n .argv;\n\nconsole.log(argv.x / argv.y);\n````\n\n***\n \n $ ./divide.js -x 55 -y 11\n 5\n \n $ node ./divide.js -x 4.91 -z 2.51\n Usage: node ./divide.js -x [num] -y [num]\n\n Options:\n -x [required]\n -y [required]\n\n Missing required arguments: y\n\nEVEN MORE HOLY COW\n------------------\n\ndefault_singles.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .default('x', 10)\n .default('y', 10)\n .argv\n;\nconsole.log(argv.x + argv.y);\n````\n\n***\n\n $ ./default_singles.js -x 5\n 15\n\ndefault_hash.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .default({ x : 10, y : 10 })\n .argv\n;\nconsole.log(argv.x + argv.y);\n````\n\n***\n\n $ ./default_hash.js -y 7\n 17\n\nAnd if you really want to get all descriptive about it...\n---------------------------------------------------------\n\nboolean_single.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .boolean('v')\n .argv\n;\nconsole.dir(argv);\n````\n\n***\n\n $ ./boolean_single.js -v foo bar baz\n true\n [ 'bar', 'baz', 'foo' ]\n\nboolean_double.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .boolean(['x','y','z'])\n .argv\n;\nconsole.dir([ argv.x, argv.y, argv.z ]);\nconsole.dir(argv._);\n````\n\n***\n\n $ ./boolean_double.js -x -z one two three\n [ true, false, true ]\n [ 'one', 'two', 'three' ]\n\nOptimist is here to help...\n---------------------------\n\nYou can describe parameters for help messages and set aliases. Optimist figures\nout how to format a handy help string automatically.\n\nline_count.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .usage('Count the lines in a file.\\nUsage: $0')\n .demand('f')\n .alias('f', 'file')\n .describe('f', 'Load a file')\n .argv\n;\n\nvar fs = require('fs');\nvar s = fs.createReadStream(argv.file);\n\nvar lines = 0;\ns.on('data', function (buf) {\n lines += buf.toString().match(/\\n/g).length;\n});\n\ns.on('end', function () {\n console.log(lines);\n});\n````\n\n***\n\n $ node line_count.js\n Count the lines in a file.\n Usage: node ./line_count.js\n\n Options:\n -f, --file Load a file [required]\n\n Missing required arguments: f\n\n $ node line_count.js --file line_count.js \n 20\n \n $ node line_count.js -f line_count.js \n 20\n\nmethods\n=======\n\nBy itself,\n\n````javascript\nrequire('optimist').argv\n`````\n\nwill use `process.argv` array to construct the `argv` object.\n\nYou can pass in the `process.argv` yourself:\n\n````javascript\nrequire('optimist')([ '-x', '1', '-y', '2' ]).argv\n````\n\nor use .parse() to do the same thing:\n\n````javascript\nrequire('optimist').parse([ '-x', '1', '-y', '2' ])\n````\n\nThe rest of these methods below come in just before the terminating `.argv`.\n\n.alias(key, alias)\n------------------\n\nSet key names as equivalent such that updates to a key will propagate to aliases\nand vice-versa.\n\nOptionally `.alias()` can take an object that maps keys to aliases.\n\n.default(key, value)\n--------------------\n\nSet `argv[key]` to `value` if no option was specified on `process.argv`.\n\nOptionally `.default()` can take an object that maps keys to default values.\n\n.demand(key)\n------------\n\nIf `key` is a string, show the usage information and exit if `key` wasn't\nspecified in `process.argv`.\n\nIf `key` is a number, demand at least as many non-option arguments, which show\nup in `argv._`.\n\nIf `key` is an Array, demand each element.\n\n.describe(key, desc)\n--------------------\n\nDescribe a `key` for the generated usage information.\n\nOptionally `.describe()` can take an object that maps keys to descriptions.\n\n.options(key, opt)\n------------------\n\nInstead of chaining together `.alias().demand().default()`, you can specify\nkeys in `opt` for each of the chainable methods.\n\nFor example:\n\n````javascript\nvar argv = require('optimist')\n .options('f', {\n alias : 'file',\n default : '/etc/passwd',\n })\n .argv\n;\n````\n\nis the same as\n\n````javascript\nvar argv = require('optimist')\n .alias('f', 'file')\n .default('f', '/etc/passwd')\n .argv\n;\n````\n\nOptionally `.options()` can take an object that maps keys to `opt` parameters.\n\n.usage(message)\n---------------\n\nSet a usage message to show which commands to use. Inside `message`, the string\n`$0` will get interpolated to the current script name or node command for the\npresent script similar to how `$0` works in bash or perl.\n\n.check(fn)\n----------\n\nCheck that certain conditions are met in the provided arguments.\n\nIf `fn` throws or returns `false`, show the thrown error, usage information, and\nexit.\n\n.boolean(key)\n-------------\n\nInterpret `key` as a boolean. If a non-flag option follows `key` in\n`process.argv`, that string won't get set as the value of `key`.\n\nIf `key` never shows up as a flag in `process.arguments`, `argv[key]` will be\n`false`.\n\nIf `key` is an Array, interpret all the elements as booleans.\n\n.string(key)\n------------\n\nTell the parser logic not to interpret `key` as a number or boolean.\nThis can be useful if you need to preserve leading zeros in an input.\n\nIf `key` is an Array, interpret all the elements as strings.\n\n.wrap(columns)\n--------------\n\nFormat usage output to wrap at `columns` many columns.\n\n.help()\n-------\n\nReturn the generated usage string.\n\n.showHelp(fn=console.error)\n---------------------------\n\nPrint the usage data using `fn` for printing.\n\n.parse(args)\n------------\n\nParse `args` instead of `process.argv`. Returns the `argv` object.\n\n.argv\n-----\n\nGet the arguments as a plain old object.\n\nArguments without a corresponding flag show up in the `argv._` array.\n\nThe script name or node command is available at `argv.$0` similarly to how `$0`\nworks in bash or perl.\n\nparsing tricks\n==============\n\nstop parsing\n------------\n\nUse `--` to stop parsing flags and stuff the remainder into `argv._`.\n\n $ node examples/reflect.js -a 1 -b 2 -- -c 3 -d 4\n { _: [ '-c', '3', '-d', '4' ],\n '$0': 'node ./examples/reflect.js',\n a: 1,\n b: 2 }\n\nnegate fields\n-------------\n\nIf you want to explicity set a field to false instead of just leaving it\nundefined or to override a default you can do `--no-key`.\n\n $ node examples/reflect.js -a --no-b\n { _: [],\n '$0': 'node ./examples/reflect.js',\n a: true,\n b: false }\n\nnumbers\n-------\n\nEvery argument that looks like a number (`!isNaN(Number(arg))`) is converted to\none. This way you can just `net.createConnection(argv.port)` and you can add\nnumbers out of `argv` with `+` without having that mean concatenation,\nwhich is super frustrating.\n\nduplicates\n----------\n\nIf you specify a flag multiple times it will get turned into an array containing\nall the values in order.\n\n $ node examples/reflect.js -x 5 -x 8 -x 0\n { _: [],\n '$0': 'node ./examples/reflect.js',\n x: [ 5, 8, 0 ] }\n\ndot notation\n------------\n\nWhen you use dots (`.`s) in argument names, an implicit object path is assumed.\nThis lets you organize arguments into nested objects.\n\n $ node examples/reflect.js --foo.bar.baz=33 --foo.quux=5\n { _: [],\n '$0': 'node ./examples/reflect.js',\n foo: { bar: { baz: 33 }, quux: 5 } }\n\nshort numbers\n-------------\n\nShort numeric `head -n5` style argument work too:\n\n $ node reflect.js -n123 -m456\n { '3': true,\n '6': true,\n _: [],\n '$0': 'node ./reflect.js',\n n: 123,\n m: 456 }\n\ninstallation\n============\n\nWith [npm](http://github.com/isaacs/npm), just do:\n npm install optimist\n \nor clone this project on github:\n\n git clone http://github.com/substack/node-optimist.git\n\nTo run the tests with [expresso](http://github.com/visionmedia/expresso),\njust do:\n \n expresso\n\ninspired By\n===========\n\nThis module is loosely inspired by Perl's\n[Getopt::Casual](http://search.cpan.org/~photo/Getopt-Casual-0.13.1/Casual.pm).\n", - "readmeFilename": "readme.markdown", - "bugs": { - "url": "https://github.com/substack/node-optimist/issues" - }, - "homepage": "https://github.com/substack/node-optimist", - "_id": "optimist@0.6.1", - "_from": "optimist@>=0.6.1 <0.7.0" -} diff --git a/node_modules/handlebars/node_modules/optimist/readme.markdown b/node_modules/handlebars/node_modules/optimist/readme.markdown deleted file mode 100644 index b74b437..0000000 --- a/node_modules/handlebars/node_modules/optimist/readme.markdown +++ /dev/null @@ -1,513 +0,0 @@ -# DEPRECATION NOTICE - -I don't want to maintain this module anymore since I just use -[minimist](https://npmjs.org/package/minimist), the argument parsing engine, -directly instead nowadays. - -See [yargs](https://github.com/chevex/yargs) for the modern, pirate-themed -successor to optimist. - -[![yarrrrrrrgs!](http://i.imgur.com/4WFGVJ9.png)](https://github.com/chevex/yargs) - -You should also consider [nomnom](https://github.com/harthur/nomnom). - -optimist -======== - -Optimist is a node.js library for option parsing for people who hate option -parsing. More specifically, this module is for people who like all the --bells -and -whistlz of program usage but think optstrings are a waste of time. - -With optimist, option parsing doesn't have to suck (as much). - -[![build status](https://secure.travis-ci.org/substack/node-optimist.png)](http://travis-ci.org/substack/node-optimist) - -examples -======== - -With Optimist, the options are just a hash! No optstrings attached. -------------------------------------------------------------------- - -xup.js: - -````javascript -#!/usr/bin/env node -var argv = require('optimist').argv; - -if (argv.rif - 5 * argv.xup > 7.138) { - console.log('Buy more riffiwobbles'); -} -else { - console.log('Sell the xupptumblers'); -} -```` - -*** - - $ ./xup.js --rif=55 --xup=9.52 - Buy more riffiwobbles - - $ ./xup.js --rif 12 --xup 8.1 - Sell the xupptumblers - -![This one's optimistic.](http://substack.net/images/optimistic.png) - -But wait! There's more! You can do short options: -------------------------------------------------- - -short.js: - -````javascript -#!/usr/bin/env node -var argv = require('optimist').argv; -console.log('(%d,%d)', argv.x, argv.y); -```` - -*** - - $ ./short.js -x 10 -y 21 - (10,21) - -And booleans, both long and short (and grouped): ----------------------------------- - -bool.js: - -````javascript -#!/usr/bin/env node -var util = require('util'); -var argv = require('optimist').argv; - -if (argv.s) { - util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: '); -} -console.log( - (argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '') -); -```` - -*** - - $ ./bool.js -s - The cat says: meow - - $ ./bool.js -sp - The cat says: meow. - - $ ./bool.js -sp --fr - Le chat dit: miaou. - -And non-hypenated options too! Just use `argv._`! -------------------------------------------------- - -nonopt.js: - -````javascript -#!/usr/bin/env node -var argv = require('optimist').argv; -console.log('(%d,%d)', argv.x, argv.y); -console.log(argv._); -```` - -*** - - $ ./nonopt.js -x 6.82 -y 3.35 moo - (6.82,3.35) - [ 'moo' ] - - $ ./nonopt.js foo -x 0.54 bar -y 1.12 baz - (0.54,1.12) - [ 'foo', 'bar', 'baz' ] - -Plus, Optimist comes with .usage() and .demand()! -------------------------------------------------- - -divide.js: - -````javascript -#!/usr/bin/env node -var argv = require('optimist') - .usage('Usage: $0 -x [num] -y [num]') - .demand(['x','y']) - .argv; - -console.log(argv.x / argv.y); -```` - -*** - - $ ./divide.js -x 55 -y 11 - 5 - - $ node ./divide.js -x 4.91 -z 2.51 - Usage: node ./divide.js -x [num] -y [num] - - Options: - -x [required] - -y [required] - - Missing required arguments: y - -EVEN MORE HOLY COW ------------------- - -default_singles.js: - -````javascript -#!/usr/bin/env node -var argv = require('optimist') - .default('x', 10) - .default('y', 10) - .argv -; -console.log(argv.x + argv.y); -```` - -*** - - $ ./default_singles.js -x 5 - 15 - -default_hash.js: - -````javascript -#!/usr/bin/env node -var argv = require('optimist') - .default({ x : 10, y : 10 }) - .argv -; -console.log(argv.x + argv.y); -```` - -*** - - $ ./default_hash.js -y 7 - 17 - -And if you really want to get all descriptive about it... ---------------------------------------------------------- - -boolean_single.js - -````javascript -#!/usr/bin/env node -var argv = require('optimist') - .boolean('v') - .argv -; -console.dir(argv); -```` - -*** - - $ ./boolean_single.js -v foo bar baz - true - [ 'bar', 'baz', 'foo' ] - -boolean_double.js - -````javascript -#!/usr/bin/env node -var argv = require('optimist') - .boolean(['x','y','z']) - .argv -; -console.dir([ argv.x, argv.y, argv.z ]); -console.dir(argv._); -```` - -*** - - $ ./boolean_double.js -x -z one two three - [ true, false, true ] - [ 'one', 'two', 'three' ] - -Optimist is here to help... ---------------------------- - -You can describe parameters for help messages and set aliases. Optimist figures -out how to format a handy help string automatically. - -line_count.js - -````javascript -#!/usr/bin/env node -var argv = require('optimist') - .usage('Count the lines in a file.\nUsage: $0') - .demand('f') - .alias('f', 'file') - .describe('f', 'Load a file') - .argv -; - -var fs = require('fs'); -var s = fs.createReadStream(argv.file); - -var lines = 0; -s.on('data', function (buf) { - lines += buf.toString().match(/\n/g).length; -}); - -s.on('end', function () { - console.log(lines); -}); -```` - -*** - - $ node line_count.js - Count the lines in a file. - Usage: node ./line_count.js - - Options: - -f, --file Load a file [required] - - Missing required arguments: f - - $ node line_count.js --file line_count.js - 20 - - $ node line_count.js -f line_count.js - 20 - -methods -======= - -By itself, - -````javascript -require('optimist').argv -````` - -will use `process.argv` array to construct the `argv` object. - -You can pass in the `process.argv` yourself: - -````javascript -require('optimist')([ '-x', '1', '-y', '2' ]).argv -```` - -or use .parse() to do the same thing: - -````javascript -require('optimist').parse([ '-x', '1', '-y', '2' ]) -```` - -The rest of these methods below come in just before the terminating `.argv`. - -.alias(key, alias) ------------------- - -Set key names as equivalent such that updates to a key will propagate to aliases -and vice-versa. - -Optionally `.alias()` can take an object that maps keys to aliases. - -.default(key, value) --------------------- - -Set `argv[key]` to `value` if no option was specified on `process.argv`. - -Optionally `.default()` can take an object that maps keys to default values. - -.demand(key) ------------- - -If `key` is a string, show the usage information and exit if `key` wasn't -specified in `process.argv`. - -If `key` is a number, demand at least as many non-option arguments, which show -up in `argv._`. - -If `key` is an Array, demand each element. - -.describe(key, desc) --------------------- - -Describe a `key` for the generated usage information. - -Optionally `.describe()` can take an object that maps keys to descriptions. - -.options(key, opt) ------------------- - -Instead of chaining together `.alias().demand().default()`, you can specify -keys in `opt` for each of the chainable methods. - -For example: - -````javascript -var argv = require('optimist') - .options('f', { - alias : 'file', - default : '/etc/passwd', - }) - .argv -; -```` - -is the same as - -````javascript -var argv = require('optimist') - .alias('f', 'file') - .default('f', '/etc/passwd') - .argv -; -```` - -Optionally `.options()` can take an object that maps keys to `opt` parameters. - -.usage(message) ---------------- - -Set a usage message to show which commands to use. Inside `message`, the string -`$0` will get interpolated to the current script name or node command for the -present script similar to how `$0` works in bash or perl. - -.check(fn) ----------- - -Check that certain conditions are met in the provided arguments. - -If `fn` throws or returns `false`, show the thrown error, usage information, and -exit. - -.boolean(key) -------------- - -Interpret `key` as a boolean. If a non-flag option follows `key` in -`process.argv`, that string won't get set as the value of `key`. - -If `key` never shows up as a flag in `process.arguments`, `argv[key]` will be -`false`. - -If `key` is an Array, interpret all the elements as booleans. - -.string(key) ------------- - -Tell the parser logic not to interpret `key` as a number or boolean. -This can be useful if you need to preserve leading zeros in an input. - -If `key` is an Array, interpret all the elements as strings. - -.wrap(columns) --------------- - -Format usage output to wrap at `columns` many columns. - -.help() -------- - -Return the generated usage string. - -.showHelp(fn=console.error) ---------------------------- - -Print the usage data using `fn` for printing. - -.parse(args) ------------- - -Parse `args` instead of `process.argv`. Returns the `argv` object. - -.argv ------ - -Get the arguments as a plain old object. - -Arguments without a corresponding flag show up in the `argv._` array. - -The script name or node command is available at `argv.$0` similarly to how `$0` -works in bash or perl. - -parsing tricks -============== - -stop parsing ------------- - -Use `--` to stop parsing flags and stuff the remainder into `argv._`. - - $ node examples/reflect.js -a 1 -b 2 -- -c 3 -d 4 - { _: [ '-c', '3', '-d', '4' ], - '$0': 'node ./examples/reflect.js', - a: 1, - b: 2 } - -negate fields -------------- - -If you want to explicity set a field to false instead of just leaving it -undefined or to override a default you can do `--no-key`. - - $ node examples/reflect.js -a --no-b - { _: [], - '$0': 'node ./examples/reflect.js', - a: true, - b: false } - -numbers -------- - -Every argument that looks like a number (`!isNaN(Number(arg))`) is converted to -one. This way you can just `net.createConnection(argv.port)` and you can add -numbers out of `argv` with `+` without having that mean concatenation, -which is super frustrating. - -duplicates ----------- - -If you specify a flag multiple times it will get turned into an array containing -all the values in order. - - $ node examples/reflect.js -x 5 -x 8 -x 0 - { _: [], - '$0': 'node ./examples/reflect.js', - x: [ 5, 8, 0 ] } - -dot notation ------------- - -When you use dots (`.`s) in argument names, an implicit object path is assumed. -This lets you organize arguments into nested objects. - - $ node examples/reflect.js --foo.bar.baz=33 --foo.quux=5 - { _: [], - '$0': 'node ./examples/reflect.js', - foo: { bar: { baz: 33 }, quux: 5 } } - -short numbers -------------- - -Short numeric `head -n5` style argument work too: - - $ node reflect.js -n123 -m456 - { '3': true, - '6': true, - _: [], - '$0': 'node ./reflect.js', - n: 123, - m: 456 } - -installation -============ - -With [npm](http://github.com/isaacs/npm), just do: - npm install optimist - -or clone this project on github: - - git clone http://github.com/substack/node-optimist.git - -To run the tests with [expresso](http://github.com/visionmedia/expresso), -just do: - - expresso - -inspired By -=========== - -This module is loosely inspired by Perl's -[Getopt::Casual](http://search.cpan.org/~photo/Getopt-Casual-0.13.1/Casual.pm). diff --git a/node_modules/handlebars/node_modules/optimist/test/_.js b/node_modules/handlebars/node_modules/optimist/test/_.js deleted file mode 100644 index d9c58b3..0000000 --- a/node_modules/handlebars/node_modules/optimist/test/_.js +++ /dev/null @@ -1,71 +0,0 @@ -var spawn = require('child_process').spawn; -var test = require('tap').test; - -test('dotSlashEmpty', testCmd('./bin.js', [])); - -test('dotSlashArgs', testCmd('./bin.js', [ 'a', 'b', 'c' ])); - -test('nodeEmpty', testCmd('node bin.js', [])); - -test('nodeArgs', testCmd('node bin.js', [ 'x', 'y', 'z' ])); - -test('whichNodeEmpty', function (t) { - var which = spawn('which', ['node']); - - which.stdout.on('data', function (buf) { - t.test( - testCmd(buf.toString().trim() + ' bin.js', []) - ); - t.end(); - }); - - which.stderr.on('data', function (err) { - assert.error(err); - t.end(); - }); -}); - -test('whichNodeArgs', function (t) { - var which = spawn('which', ['node']); - - which.stdout.on('data', function (buf) { - t.test( - testCmd(buf.toString().trim() + ' bin.js', [ 'q', 'r' ]) - ); - t.end(); - }); - - which.stderr.on('data', function (err) { - t.error(err); - t.end(); - }); -}); - -function testCmd (cmd, args) { - - return function (t) { - var to = setTimeout(function () { - assert.fail('Never got stdout data.') - }, 5000); - - var oldDir = process.cwd(); - process.chdir(__dirname + '/_'); - - var cmds = cmd.split(' '); - - var bin = spawn(cmds[0], cmds.slice(1).concat(args.map(String))); - process.chdir(oldDir); - - bin.stderr.on('data', function (err) { - t.error(err); - t.end(); - }); - - bin.stdout.on('data', function (buf) { - clearTimeout(to); - var _ = JSON.parse(buf.toString()); - t.same(_.map(String), args.map(String)); - t.end(); - }); - }; -} diff --git a/node_modules/handlebars/node_modules/optimist/test/_/argv.js b/node_modules/handlebars/node_modules/optimist/test/_/argv.js deleted file mode 100644 index 3d09606..0000000 --- a/node_modules/handlebars/node_modules/optimist/test/_/argv.js +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env node -console.log(JSON.stringify(process.argv)); diff --git a/node_modules/handlebars/node_modules/optimist/test/_/bin.js b/node_modules/handlebars/node_modules/optimist/test/_/bin.js deleted file mode 100755 index 4a18d85..0000000 --- a/node_modules/handlebars/node_modules/optimist/test/_/bin.js +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env node -var argv = require('../../index').argv -console.log(JSON.stringify(argv._)); diff --git a/node_modules/handlebars/node_modules/optimist/test/parse.js b/node_modules/handlebars/node_modules/optimist/test/parse.js deleted file mode 100644 index d320f43..0000000 --- a/node_modules/handlebars/node_modules/optimist/test/parse.js +++ /dev/null @@ -1,446 +0,0 @@ -var optimist = require('../index'); -var path = require('path'); -var test = require('tap').test; - -var $0 = 'node ./' + path.relative(process.cwd(), __filename); - -test('short boolean', function (t) { - var parse = optimist.parse([ '-b' ]); - t.same(parse, { b : true, _ : [], $0 : $0 }); - t.same(typeof parse.b, 'boolean'); - t.end(); -}); - -test('long boolean', function (t) { - t.same( - optimist.parse([ '--bool' ]), - { bool : true, _ : [], $0 : $0 } - ); - t.end(); -}); - -test('bare', function (t) { - t.same( - optimist.parse([ 'foo', 'bar', 'baz' ]), - { _ : [ 'foo', 'bar', 'baz' ], $0 : $0 } - ); - t.end(); -}); - -test('short group', function (t) { - t.same( - optimist.parse([ '-cats' ]), - { c : true, a : true, t : true, s : true, _ : [], $0 : $0 } - ); - t.end(); -}); - -test('short group next', function (t) { - t.same( - optimist.parse([ '-cats', 'meow' ]), - { c : true, a : true, t : true, s : 'meow', _ : [], $0 : $0 } - ); - t.end(); -}); - -test('short capture', function (t) { - t.same( - optimist.parse([ '-h', 'localhost' ]), - { h : 'localhost', _ : [], $0 : $0 } - ); - t.end(); -}); - -test('short captures', function (t) { - t.same( - optimist.parse([ '-h', 'localhost', '-p', '555' ]), - { h : 'localhost', p : 555, _ : [], $0 : $0 } - ); - t.end(); -}); - -test('long capture sp', function (t) { - t.same( - optimist.parse([ '--pow', 'xixxle' ]), - { pow : 'xixxle', _ : [], $0 : $0 } - ); - t.end(); -}); - -test('long capture eq', function (t) { - t.same( - optimist.parse([ '--pow=xixxle' ]), - { pow : 'xixxle', _ : [], $0 : $0 } - ); - t.end() -}); - -test('long captures sp', function (t) { - t.same( - optimist.parse([ '--host', 'localhost', '--port', '555' ]), - { host : 'localhost', port : 555, _ : [], $0 : $0 } - ); - t.end(); -}); - -test('long captures eq', function (t) { - t.same( - optimist.parse([ '--host=localhost', '--port=555' ]), - { host : 'localhost', port : 555, _ : [], $0 : $0 } - ); - t.end(); -}); - -test('mixed short bool and capture', function (t) { - t.same( - optimist.parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]), - { - f : true, p : 555, h : 'localhost', - _ : [ 'script.js' ], $0 : $0, - } - ); - t.end(); -}); - -test('short and long', function (t) { - t.same( - optimist.parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]), - { - f : true, p : 555, h : 'localhost', - _ : [ 'script.js' ], $0 : $0, - } - ); - t.end(); -}); - -test('no', function (t) { - t.same( - optimist.parse([ '--no-moo' ]), - { moo : false, _ : [], $0 : $0 } - ); - t.end(); -}); - -test('multi', function (t) { - t.same( - optimist.parse([ '-v', 'a', '-v', 'b', '-v', 'c' ]), - { v : ['a','b','c'], _ : [], $0 : $0 } - ); - t.end(); -}); - -test('comprehensive', function (t) { - t.same( - optimist.parse([ - '--name=meowmers', 'bare', '-cats', 'woo', - '-h', 'awesome', '--multi=quux', - '--key', 'value', - '-b', '--bool', '--no-meep', '--multi=baz', - '--', '--not-a-flag', 'eek' - ]), - { - c : true, - a : true, - t : true, - s : 'woo', - h : 'awesome', - b : true, - bool : true, - key : 'value', - multi : [ 'quux', 'baz' ], - meep : false, - name : 'meowmers', - _ : [ 'bare', '--not-a-flag', 'eek' ], - $0 : $0 - } - ); - t.end(); -}); - -test('nums', function (t) { - var argv = optimist.parse([ - '-x', '1234', - '-y', '5.67', - '-z', '1e7', - '-w', '10f', - '--hex', '0xdeadbeef', - '789', - ]); - t.same(argv, { - x : 1234, - y : 5.67, - z : 1e7, - w : '10f', - hex : 0xdeadbeef, - _ : [ 789 ], - $0 : $0 - }); - t.same(typeof argv.x, 'number'); - t.same(typeof argv.y, 'number'); - t.same(typeof argv.z, 'number'); - t.same(typeof argv.w, 'string'); - t.same(typeof argv.hex, 'number'); - t.same(typeof argv._[0], 'number'); - t.end(); -}); - -test('flag boolean', function (t) { - var parse = optimist([ '-t', 'moo' ]).boolean(['t']).argv; - t.same(parse, { t : true, _ : [ 'moo' ], $0 : $0 }); - t.same(typeof parse.t, 'boolean'); - t.end(); -}); - -test('flag boolean value', function (t) { - var parse = optimist(['--verbose', 'false', 'moo', '-t', 'true']) - .boolean(['t', 'verbose']).default('verbose', true).argv; - - t.same(parse, { - verbose: false, - t: true, - _: ['moo'], - $0 : $0 - }); - - t.same(typeof parse.verbose, 'boolean'); - t.same(typeof parse.t, 'boolean'); - t.end(); -}); - -test('flag boolean default false', function (t) { - var parse = optimist(['moo']) - .boolean(['t', 'verbose']) - .default('verbose', false) - .default('t', false).argv; - - t.same(parse, { - verbose: false, - t: false, - _: ['moo'], - $0 : $0 - }); - - t.same(typeof parse.verbose, 'boolean'); - t.same(typeof parse.t, 'boolean'); - t.end(); - -}); - -test('boolean groups', function (t) { - var parse = optimist([ '-x', '-z', 'one', 'two', 'three' ]) - .boolean(['x','y','z']).argv; - - t.same(parse, { - x : true, - y : false, - z : true, - _ : [ 'one', 'two', 'three' ], - $0 : $0 - }); - - t.same(typeof parse.x, 'boolean'); - t.same(typeof parse.y, 'boolean'); - t.same(typeof parse.z, 'boolean'); - t.end(); -}); - -test('newlines in params' , function (t) { - var args = optimist.parse([ '-s', "X\nX" ]) - t.same(args, { _ : [], s : "X\nX", $0 : $0 }); - - // reproduce in bash: - // VALUE="new - // line" - // node program.js --s="$VALUE" - args = optimist.parse([ "--s=X\nX" ]) - t.same(args, { _ : [], s : "X\nX", $0 : $0 }); - t.end(); -}); - -test('strings' , function (t) { - var s = optimist([ '-s', '0001234' ]).string('s').argv.s; - t.same(s, '0001234'); - t.same(typeof s, 'string'); - - var x = optimist([ '-x', '56' ]).string('x').argv.x; - t.same(x, '56'); - t.same(typeof x, 'string'); - t.end(); -}); - -test('stringArgs', function (t) { - var s = optimist([ ' ', ' ' ]).string('_').argv._; - t.same(s.length, 2); - t.same(typeof s[0], 'string'); - t.same(s[0], ' '); - t.same(typeof s[1], 'string'); - t.same(s[1], ' '); - t.end(); -}); - -test('slashBreak', function (t) { - t.same( - optimist.parse([ '-I/foo/bar/baz' ]), - { I : '/foo/bar/baz', _ : [], $0 : $0 } - ); - t.same( - optimist.parse([ '-xyz/foo/bar/baz' ]), - { x : true, y : true, z : '/foo/bar/baz', _ : [], $0 : $0 } - ); - t.end(); -}); - -test('alias', function (t) { - var argv = optimist([ '-f', '11', '--zoom', '55' ]) - .alias('z', 'zoom') - .argv - ; - t.equal(argv.zoom, 55); - t.equal(argv.z, argv.zoom); - t.equal(argv.f, 11); - t.end(); -}); - -test('multiAlias', function (t) { - var argv = optimist([ '-f', '11', '--zoom', '55' ]) - .alias('z', [ 'zm', 'zoom' ]) - .argv - ; - t.equal(argv.zoom, 55); - t.equal(argv.z, argv.zoom); - t.equal(argv.z, argv.zm); - t.equal(argv.f, 11); - t.end(); -}); - -test('boolean default true', function (t) { - var argv = optimist.options({ - sometrue: { - boolean: true, - default: true - } - }).argv; - - t.equal(argv.sometrue, true); - t.end(); -}); - -test('boolean default false', function (t) { - var argv = optimist.options({ - somefalse: { - boolean: true, - default: false - } - }).argv; - - t.equal(argv.somefalse, false); - t.end(); -}); - -test('nested dotted objects', function (t) { - var argv = optimist([ - '--foo.bar', '3', '--foo.baz', '4', - '--foo.quux.quibble', '5', '--foo.quux.o_O', - '--beep.boop' - ]).argv; - - t.same(argv.foo, { - bar : 3, - baz : 4, - quux : { - quibble : 5, - o_O : true - }, - }); - t.same(argv.beep, { boop : true }); - t.end(); -}); - -test('boolean and alias with chainable api', function (t) { - var aliased = [ '-h', 'derp' ]; - var regular = [ '--herp', 'derp' ]; - var opts = { - herp: { alias: 'h', boolean: true } - }; - var aliasedArgv = optimist(aliased) - .boolean('herp') - .alias('h', 'herp') - .argv; - var propertyArgv = optimist(regular) - .boolean('herp') - .alias('h', 'herp') - .argv; - var expected = { - herp: true, - h: true, - '_': [ 'derp' ], - '$0': $0, - }; - - t.same(aliasedArgv, expected); - t.same(propertyArgv, expected); - t.end(); -}); - -test('boolean and alias with options hash', function (t) { - var aliased = [ '-h', 'derp' ]; - var regular = [ '--herp', 'derp' ]; - var opts = { - herp: { alias: 'h', boolean: true } - }; - var aliasedArgv = optimist(aliased) - .options(opts) - .argv; - var propertyArgv = optimist(regular).options(opts).argv; - var expected = { - herp: true, - h: true, - '_': [ 'derp' ], - '$0': $0, - }; - - t.same(aliasedArgv, expected); - t.same(propertyArgv, expected); - - t.end(); -}); - -test('boolean and alias using explicit true', function (t) { - var aliased = [ '-h', 'true' ]; - var regular = [ '--herp', 'true' ]; - var opts = { - herp: { alias: 'h', boolean: true } - }; - var aliasedArgv = optimist(aliased) - .boolean('h') - .alias('h', 'herp') - .argv; - var propertyArgv = optimist(regular) - .boolean('h') - .alias('h', 'herp') - .argv; - var expected = { - herp: true, - h: true, - '_': [ ], - '$0': $0, - }; - - t.same(aliasedArgv, expected); - t.same(propertyArgv, expected); - t.end(); -}); - -// regression, see https://github.com/substack/node-optimist/issues/71 -test('boolean and --x=true', function(t) { - var parsed = optimist(['--boool', '--other=true']).boolean('boool').argv; - - t.same(parsed.boool, true); - t.same(parsed.other, 'true'); - - parsed = optimist(['--boool', '--other=false']).boolean('boool').argv; - - t.same(parsed.boool, true); - t.same(parsed.other, 'false'); - t.end(); -}); diff --git a/node_modules/handlebars/node_modules/optimist/test/usage.js b/node_modules/handlebars/node_modules/optimist/test/usage.js deleted file mode 100644 index 300454c..0000000 --- a/node_modules/handlebars/node_modules/optimist/test/usage.js +++ /dev/null @@ -1,292 +0,0 @@ -var Hash = require('hashish'); -var optimist = require('../index'); -var test = require('tap').test; - -test('usageFail', function (t) { - var r = checkUsage(function () { - return optimist('-x 10 -z 20'.split(' ')) - .usage('Usage: $0 -x NUM -y NUM') - .demand(['x','y']) - .argv; - }); - t.same( - r.result, - { x : 10, z : 20, _ : [], $0 : './usage' } - ); - - t.same( - r.errors.join('\n').split(/\n+/), - [ - 'Usage: ./usage -x NUM -y NUM', - 'Options:', - ' -x [required]', - ' -y [required]', - 'Missing required arguments: y', - ] - ); - t.same(r.logs, []); - t.ok(r.exit); - t.end(); -}); - - -test('usagePass', function (t) { - var r = checkUsage(function () { - return optimist('-x 10 -y 20'.split(' ')) - .usage('Usage: $0 -x NUM -y NUM') - .demand(['x','y']) - .argv; - }); - t.same(r, { - result : { x : 10, y : 20, _ : [], $0 : './usage' }, - errors : [], - logs : [], - exit : false, - }); - t.end(); -}); - -test('checkPass', function (t) { - var r = checkUsage(function () { - return optimist('-x 10 -y 20'.split(' ')) - .usage('Usage: $0 -x NUM -y NUM') - .check(function (argv) { - if (!('x' in argv)) throw 'You forgot about -x'; - if (!('y' in argv)) throw 'You forgot about -y'; - }) - .argv; - }); - t.same(r, { - result : { x : 10, y : 20, _ : [], $0 : './usage' }, - errors : [], - logs : [], - exit : false, - }); - t.end(); -}); - -test('checkFail', function (t) { - var r = checkUsage(function () { - return optimist('-x 10 -z 20'.split(' ')) - .usage('Usage: $0 -x NUM -y NUM') - .check(function (argv) { - if (!('x' in argv)) throw 'You forgot about -x'; - if (!('y' in argv)) throw 'You forgot about -y'; - }) - .argv; - }); - - t.same( - r.result, - { x : 10, z : 20, _ : [], $0 : './usage' } - ); - - t.same( - r.errors.join('\n').split(/\n+/), - [ - 'Usage: ./usage -x NUM -y NUM', - 'You forgot about -y' - ] - ); - - t.same(r.logs, []); - t.ok(r.exit); - t.end(); -}); - -test('checkCondPass', function (t) { - function checker (argv) { - return 'x' in argv && 'y' in argv; - } - - var r = checkUsage(function () { - return optimist('-x 10 -y 20'.split(' ')) - .usage('Usage: $0 -x NUM -y NUM') - .check(checker) - .argv; - }); - t.same(r, { - result : { x : 10, y : 20, _ : [], $0 : './usage' }, - errors : [], - logs : [], - exit : false, - }); - t.end(); -}); - -test('checkCondFail', function (t) { - function checker (argv) { - return 'x' in argv && 'y' in argv; - } - - var r = checkUsage(function () { - return optimist('-x 10 -z 20'.split(' ')) - .usage('Usage: $0 -x NUM -y NUM') - .check(checker) - .argv; - }); - - t.same( - r.result, - { x : 10, z : 20, _ : [], $0 : './usage' } - ); - - t.same( - r.errors.join('\n').split(/\n+/).join('\n'), - 'Usage: ./usage -x NUM -y NUM\n' - + 'Argument check failed: ' + checker.toString() - ); - - t.same(r.logs, []); - t.ok(r.exit); - t.end(); -}); - -test('countPass', function (t) { - var r = checkUsage(function () { - return optimist('1 2 3 --moo'.split(' ')) - .usage('Usage: $0 [x] [y] [z] {OPTIONS}') - .demand(3) - .argv; - }); - t.same(r, { - result : { _ : [ '1', '2', '3' ], moo : true, $0 : './usage' }, - errors : [], - logs : [], - exit : false, - }); - t.end(); -}); - -test('countFail', function (t) { - var r = checkUsage(function () { - return optimist('1 2 --moo'.split(' ')) - .usage('Usage: $0 [x] [y] [z] {OPTIONS}') - .demand(3) - .argv; - }); - t.same( - r.result, - { _ : [ '1', '2' ], moo : true, $0 : './usage' } - ); - - t.same( - r.errors.join('\n').split(/\n+/), - [ - 'Usage: ./usage [x] [y] [z] {OPTIONS}', - 'Not enough non-option arguments: got 2, need at least 3', - ] - ); - - t.same(r.logs, []); - t.ok(r.exit); - t.end(); -}); - -test('defaultSingles', function (t) { - var r = checkUsage(function () { - return optimist('--foo 50 --baz 70 --powsy'.split(' ')) - .default('foo', 5) - .default('bar', 6) - .default('baz', 7) - .argv - ; - }); - t.same(r.result, { - foo : '50', - bar : 6, - baz : '70', - powsy : true, - _ : [], - $0 : './usage', - }); - t.end(); -}); - -test('defaultAliases', function (t) { - var r = checkUsage(function () { - return optimist('') - .alias('f', 'foo') - .default('f', 5) - .argv - ; - }); - t.same(r.result, { - f : '5', - foo : '5', - _ : [], - $0 : './usage', - }); - t.end(); -}); - -test('defaultHash', function (t) { - var r = checkUsage(function () { - return optimist('--foo 50 --baz 70'.split(' ')) - .default({ foo : 10, bar : 20, quux : 30 }) - .argv - ; - }); - t.same(r.result, { - _ : [], - $0 : './usage', - foo : 50, - baz : 70, - bar : 20, - quux : 30, - }); - t.end(); -}); - -test('rebase', function (t) { - t.equal( - optimist.rebase('/home/substack', '/home/substack/foo/bar/baz'), - './foo/bar/baz' - ); - t.equal( - optimist.rebase('/home/substack/foo/bar/baz', '/home/substack'), - '../../..' - ); - t.equal( - optimist.rebase('/home/substack/foo', '/home/substack/pow/zoom.txt'), - '../pow/zoom.txt' - ); - t.end(); -}); - -function checkUsage (f) { - - var exit = false; - - process._exit = process.exit; - process._env = process.env; - process._argv = process.argv; - - process.exit = function (t) { exit = true }; - process.env = Hash.merge(process.env, { _ : 'node' }); - process.argv = [ './usage' ]; - - var errors = []; - var logs = []; - - console._error = console.error; - console.error = function (msg) { errors.push(msg) }; - console._log = console.log; - console.log = function (msg) { logs.push(msg) }; - - var result = f(); - - process.exit = process._exit; - process.env = process._env; - process.argv = process._argv; - - console.error = console._error; - console.log = console._log; - - return { - errors : errors, - logs : logs, - exit : exit, - result : result, - }; -}; diff --git a/node_modules/handlebars/node_modules/uglify-js/.npmignore b/node_modules/handlebars/node_modules/uglify-js/.npmignore deleted file mode 100644 index 94fceeb..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -tmp/ -node_modules/ diff --git a/node_modules/handlebars/node_modules/uglify-js/.travis.yml b/node_modules/handlebars/node_modules/uglify-js/.travis.yml deleted file mode 100644 index d959127..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: node_js -node_js: - - "0.4" - - "0.6" - - "0.8" - - "0.10" - - "0.11" diff --git a/node_modules/handlebars/node_modules/uglify-js/LICENSE b/node_modules/handlebars/node_modules/uglify-js/LICENSE deleted file mode 100644 index dd7706f..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -UglifyJS is released under the BSD license: - -Copyright 2012-2013 (c) Mihai Bazon - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above - copyright notice, this list of conditions and the following - disclaimer. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, -OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR -TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. diff --git a/node_modules/handlebars/node_modules/uglify-js/README.md b/node_modules/handlebars/node_modules/uglify-js/README.md deleted file mode 100644 index 749b8ce..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/README.md +++ /dev/null @@ -1,588 +0,0 @@ -UglifyJS 2 -========== -[![Build Status](https://travis-ci.org/mishoo/UglifyJS2.png)](https://travis-ci.org/mishoo/UglifyJS2) - -UglifyJS is a JavaScript parser, minifier, compressor or beautifier toolkit. - -This page documents the command line utility. For -[API and internals documentation see my website](http://lisperator.net/uglifyjs/). -There's also an -[in-browser online demo](http://lisperator.net/uglifyjs/#demo) (for Firefox, -Chrome and probably Safari). - -Install -------- - -First make sure you have installed the latest version of [node.js](http://nodejs.org/) -(You may need to restart your computer after this step). - -From NPM for use as a command line app: - - npm install uglify-js -g - -From NPM for programmatic use: - - npm install uglify-js - -From Git: - - git clone git://github.com/mishoo/UglifyJS2.git - cd UglifyJS2 - npm link . - -Usage ------ - - uglifyjs [input files] [options] - -UglifyJS2 can take multiple input files. It's recommended that you pass the -input files first, then pass the options. UglifyJS will parse input files -in sequence and apply any compression options. The files are parsed in the -same global scope, that is, a reference from a file to some -variable/function declared in another file will be matched properly. - -If you want to read from STDIN instead, pass a single dash instead of input -files. - -The available options are: - - --source-map Specify an output file where to generate source map. - [string] - --source-map-root The path to the original source to be included in the - source map. [string] - --source-map-url The path to the source map to be added in //@ - sourceMappingURL. Defaults to the value passed with - --source-map. [string] - --in-source-map Input source map, useful if you're compressing JS that was - generated from some other original code. - --screw-ie8 Pass this flag if you don't care about full compliance with - Internet Explorer 6-8 quirks (by default UglifyJS will try - to be IE-proof). - -p, --prefix Skip prefix for original filenames that appear in source - maps. For example -p 3 will drop 3 directories from file - names and ensure they are relative paths. - -o, --output Output file (default STDOUT). - -b, --beautify Beautify output/specify output options. [string] - -m, --mangle Mangle names/pass mangler options. [string] - -r, --reserved Reserved names to exclude from mangling. - -c, --compress Enable compressor/pass compressor options. Pass options - like -c hoist_vars=false,if_return=false. Use -c with no - argument to use the default compression options. [string] - -d, --define Global definitions [string] - --comments Preserve copyright comments in the output. By default this - works like Google Closure, keeping JSDoc-style comments - that contain "@license" or "@preserve". You can optionally - pass one of the following arguments to this flag: - - "all" to keep all comments - - a valid JS regexp (needs to start with a slash) to keep - only comments that match. - Note that currently not *all* comments can be kept when - compression is on, because of dead code removal or - cascading statements into sequences. [string] - --stats Display operations run time on STDERR. [boolean] - --acorn Use Acorn for parsing. [boolean] - --spidermonkey Assume input files are SpiderMonkey AST format (as JSON). - [boolean] - --self Build itself (UglifyJS2) as a library (implies - --wrap=UglifyJS --export-all) [boolean] - --wrap Embed everything in a big function, making the “exports” - and “global” variables available. You need to pass an - argument to this option to specify the name that your - module will take when included in, say, a browser. - [string] - --export-all Only used when --wrap, this tells UglifyJS to add code to - automatically export all globals. [boolean] - --lint Display some scope warnings [boolean] - -v, --verbose Verbose [boolean] - -V, --version Print version number and exit. [boolean] - -Specify `--output` (`-o`) to declare the output file. Otherwise the output -goes to STDOUT. - -## Source map options - -UglifyJS2 can generate a source map file, which is highly useful for -debugging your compressed JavaScript. To get a source map, pass -`--source-map output.js.map` (full path to the file where you want the -source map dumped). - -Additionally you might need `--source-map-root` to pass the URL where the -original files can be found. In case you are passing full paths to input -files to UglifyJS, you can use `--prefix` (`-p`) to specify the number of -directories to drop from the path prefix when declaring files in the source -map. - -For example: - - uglifyjs /home/doe/work/foo/src/js/file1.js \ - /home/doe/work/foo/src/js/file2.js \ - -o foo.min.js \ - --source-map foo.min.js.map \ - --source-map-root http://foo.com/src \ - -p 5 -c -m - -The above will compress and mangle `file1.js` and `file2.js`, will drop the -output in `foo.min.js` and the source map in `foo.min.js.map`. The source -mapping will refer to `http://foo.com/src/js/file1.js` and -`http://foo.com/src/js/file2.js` (in fact it will list `http://foo.com/src` -as the source map root, and the original files as `js/file1.js` and -`js/file2.js`). - -### Composed source map - -When you're compressing JS code that was output by a compiler such as -CoffeeScript, mapping to the JS code won't be too helpful. Instead, you'd -like to map back to the original code (i.e. CoffeeScript). UglifyJS has an -option to take an input source map. Assuming you have a mapping from -CoffeeScript → compiled JS, UglifyJS can generate a map from CoffeeScript → -compressed JS by mapping every token in the compiled JS to its original -location. - -To use this feature you need to pass `--in-source-map -/path/to/input/source.map`. Normally the input source map should also point -to the file containing the generated JS, so if that's correct you can omit -input files from the command line. - -## Mangler options - -To enable the mangler you need to pass `--mangle` (`-m`). The following -(comma-separated) options are supported: - -- `sort` — to assign shorter names to most frequently used variables. This - saves a few hundred bytes on jQuery before gzip, but the output is - _bigger_ after gzip (and seems to happen for other libraries I tried it - on) therefore it's not enabled by default. - -- `toplevel` — mangle names declared in the toplevel scope (disabled by - default). - -- `eval` — mangle names visible in scopes where `eval` or `when` are used - (disabled by default). - -When mangling is enabled but you want to prevent certain names from being -mangled, you can declare those names with `--reserved` (`-r`) — pass a -comma-separated list of names. For example: - - uglifyjs ... -m -r '$,require,exports' - -to prevent the `require`, `exports` and `$` names from being changed. - -## Compressor options - -You need to pass `--compress` (`-c`) to enable the compressor. Optionally -you can pass a comma-separated list of options. Options are in the form -`foo=bar`, or just `foo` (the latter implies a boolean option that you want -to set `true`; it's effectively a shortcut for `foo=true`). - -- `sequences` -- join consecutive simple statements using the comma operator -- `properties` -- rewrite property access using the dot notation, for - example `foo["bar"] → foo.bar` -- `dead_code` -- remove unreachable code -- `drop_debugger` -- remove `debugger;` statements -- `unsafe` (default: false) -- apply "unsafe" transformations (discussion below) -- `conditionals` -- apply optimizations for `if`-s and conditional - expressions -- `comparisons` -- apply certain optimizations to binary nodes, for example: - `!(a <= b) → a > b` (only when `unsafe`), attempts to negate binary nodes, - e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc. -- `evaluate` -- attempt to evaluate constant expressions -- `booleans` -- various optimizations for boolean context, for example `!!a - ? b : c → a ? b : c` -- `loops` -- optimizations for `do`, `while` and `for` loops when we can - statically determine the condition -- `unused` -- drop unreferenced functions and variables -- `hoist_funs` -- hoist function declarations -- `hoist_vars` (default: false) -- hoist `var` declarations (this is `false` - by default because it seems to increase the size of the output in general) -- `if_return` -- optimizations for if/return and if/continue -- `join_vars` -- join consecutive `var` statements -- `cascade` -- small optimization for sequences, transform `x, x` into `x` - and `x = something(), x` into `x = something()` -- `warnings` -- display warnings when dropping unreachable code or unused - declarations etc. - -### The `unsafe` option - -It enables some transformations that *might* break code logic in certain -contrived cases, but should be fine for most code. You might want to try it -on your own code, it should reduce the minified size. Here's what happens -when this flag is on: - -- `new Array(1, 2, 3)` or `Array(1, 2, 3)` → `[1, 2, 3 ]` -- `new Object()` → `{}` -- `String(exp)` or `exp.toString()` → `"" + exp` -- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new` -- `typeof foo == "undefined"` → `foo === void 0` -- `void 0` → `"undefined"` (if there is a variable named "undefined" in - scope; we do it because the variable name will be mangled, typically - reduced to a single character). - -### Conditional compilation - -You can use the `--define` (`-d`) switch in order to declare global -variables that UglifyJS will assume to be constants (unless defined in -scope). For example if you pass `--define DEBUG=false` then, coupled with -dead code removal UglifyJS will discard the following from the output: -```javascript -if (DEBUG) { - console.log("debug stuff"); -} -``` - -UglifyJS will warn about the condition being always false and about dropping -unreachable code; for now there is no option to turn off only this specific -warning, you can pass `warnings=false` to turn off *all* warnings. - -Another way of doing that is to declare your globals as constants in a -separate file and include it into the build. For example you can have a -`build/defines.js` file with the following: -```javascript -const DEBUG = false; -const PRODUCTION = true; -// etc. -``` - -and build your code like this: - - uglifyjs build/defines.js js/foo.js js/bar.js... -c - -UglifyJS will notice the constants and, since they cannot be altered, it -will evaluate references to them to the value itself and drop unreachable -code as usual. The possible downside of this approach is that the build -will contain the `const` declarations. - - -## Beautifier options - -The code generator tries to output shortest code possible by default. In -case you want beautified output, pass `--beautify` (`-b`). Optionally you -can pass additional arguments that control the code output: - -- `beautify` (default `true`) -- whether to actually beautify the output. - Passing `-b` will set this to true, but you might need to pass `-b` even - when you want to generate minified code, in order to specify additional - arguments, so you can use `-b beautify=false` to override it. -- `indent-level` (default 4) -- `indent-start` (default 0) -- prefix all lines by that many spaces -- `quote-keys` (default `false`) -- pass `true` to quote all keys in literal - objects -- `space-colon` (default `true`) -- insert a space after the colon signs -- `ascii-only` (default `false`) -- escape Unicode characters in strings and - regexps -- `inline-script` (default `false`) -- escape the slash in occurrences of - ` 0) { - sys.error("WARN: Ignoring input files since --self was passed"); - } - files = UglifyJS.FILES; - if (!ARGS.wrap) ARGS.wrap = "UglifyJS"; - ARGS.export_all = true; -} - -var ORIG_MAP = ARGS.in_source_map; - -if (ORIG_MAP) { - ORIG_MAP = JSON.parse(fs.readFileSync(ORIG_MAP)); - if (files.length == 0) { - sys.error("INFO: Using file from the input source map: " + ORIG_MAP.file); - files = [ ORIG_MAP.file ]; - } - if (ARGS.source_map_root == null) { - ARGS.source_map_root = ORIG_MAP.sourceRoot; - } -} - -if (files.length == 0) { - files = [ "-" ]; -} - -if (files.indexOf("-") >= 0 && ARGS.source_map) { - sys.error("ERROR: Source map doesn't work with input from STDIN"); - process.exit(1); -} - -if (files.filter(function(el){ return el == "-" }).length > 1) { - sys.error("ERROR: Can read a single file from STDIN (two or more dashes specified)"); - process.exit(1); -} - -var STATS = {}; -var OUTPUT_FILE = ARGS.o; -var TOPLEVEL = null; - -var SOURCE_MAP = ARGS.source_map ? UglifyJS.SourceMap({ - file: OUTPUT_FILE, - root: ARGS.source_map_root, - orig: ORIG_MAP, -}) : null; - -OUTPUT_OPTIONS.source_map = SOURCE_MAP; - -try { - var output = UglifyJS.OutputStream(OUTPUT_OPTIONS); - var compressor = COMPRESS && UglifyJS.Compressor(COMPRESS); -} catch(ex) { - if (ex instanceof UglifyJS.DefaultsError) { - sys.error(ex.msg); - sys.error("Supported options:"); - sys.error(sys.inspect(ex.defs)); - process.exit(1); - } -} - -async.eachLimit(files, 1, function (file, cb) { - read_whole_file(file, function (err, code) { - if (err) { - sys.error("ERROR: can't read file: " + filename); - process.exit(1); - } - if (ARGS.p != null) { - file = file.replace(/^\/+/, "").split(/\/+/).slice(ARGS.p).join("/"); - } - time_it("parse", function(){ - if (ARGS.spidermonkey) { - var program = JSON.parse(code); - if (!TOPLEVEL) TOPLEVEL = program; - else TOPLEVEL.body = TOPLEVEL.body.concat(program.body); - } - else if (ARGS.acorn) { - TOPLEVEL = acorn.parse(code, { - locations : true, - trackComments : true, - sourceFile : file, - program : TOPLEVEL - }); - } - else { - TOPLEVEL = UglifyJS.parse(code, { - filename : file, - toplevel : TOPLEVEL, - expression : ARGS.expr, - }); - }; - }); - cb(); - }); -}, function () { - if (ARGS.acorn || ARGS.spidermonkey) time_it("convert_ast", function(){ - TOPLEVEL = UglifyJS.AST_Node.from_mozilla_ast(TOPLEVEL); - }); - - if (ARGS.wrap) { - TOPLEVEL = TOPLEVEL.wrap_commonjs(ARGS.wrap, ARGS.export_all); - } - - if (ARGS.enclose) { - var arg_parameter_list = ARGS.enclose; - - if (!(arg_parameter_list instanceof Array)) { - arg_parameter_list = [arg_parameter_list]; - } - - TOPLEVEL = TOPLEVEL.wrap_enclose(arg_parameter_list); - } - - var SCOPE_IS_NEEDED = COMPRESS || MANGLE || ARGS.lint; - - if (SCOPE_IS_NEEDED) { - time_it("scope", function(){ - TOPLEVEL.figure_out_scope({ screw_ie8: ARGS.screw_ie8 }); - if (ARGS.lint) { - TOPLEVEL.scope_warnings(); - } - }); - } - - if (COMPRESS) { - time_it("squeeze", function(){ - TOPLEVEL = TOPLEVEL.transform(compressor); - }); - } - - if (SCOPE_IS_NEEDED) { - time_it("scope", function(){ - TOPLEVEL.figure_out_scope({ screw_ie8: ARGS.screw_ie8 }); - if (MANGLE) { - TOPLEVEL.compute_char_frequency(MANGLE); - } - }); - } - - if (MANGLE) time_it("mangle", function(){ - TOPLEVEL.mangle_names(MANGLE); - }); - time_it("generate", function(){ - TOPLEVEL.print(output); - }); - - output = output.get(); - - if (SOURCE_MAP) { - fs.writeFileSync(ARGS.source_map, SOURCE_MAP, "utf8"); - output += "\n//# sourceMappingURL=" + (ARGS.source_map_url || ARGS.source_map); - } - - if (OUTPUT_FILE) { - fs.writeFileSync(OUTPUT_FILE, output, "utf8"); - } else { - sys.print(output); - sys.error("\n"); - } - - if (ARGS.stats) { - sys.error(UglifyJS.string_template("Timing information (compressed {count} files):", { - count: files.length - })); - for (var i in STATS) if (STATS.hasOwnProperty(i)) { - sys.error(UglifyJS.string_template("- {name}: {time}s", { - name: i, - time: (STATS[i] / 1000).toFixed(3) - })); - } - } -}); - -/* -----[ functions ]----- */ - -function normalize(o) { - for (var i in o) if (o.hasOwnProperty(i) && /-/.test(i)) { - o[i.replace(/-/g, "_")] = o[i]; - delete o[i]; - } -} - -function getOptions(x, constants) { - x = ARGS[x]; - if (!x) return null; - var ret = {}; - if (x !== true) { - var ast; - try { - ast = UglifyJS.parse(x); - } catch(ex) { - if (ex instanceof UglifyJS.JS_Parse_Error) { - sys.error("Error parsing arguments in: " + x); - process.exit(1); - } - } - ast.walk(new UglifyJS.TreeWalker(function(node){ - if (node instanceof UglifyJS.AST_Toplevel) return; // descend - if (node instanceof UglifyJS.AST_SimpleStatement) return; // descend - if (node instanceof UglifyJS.AST_Seq) return; // descend - if (node instanceof UglifyJS.AST_Assign) { - var name = node.left.print_to_string({ beautify: false }).replace(/-/g, "_"); - var value = node.right; - if (constants) - value = new Function("return (" + value.print_to_string() + ")")(); - ret[name] = value; - return true; // no descend - } - sys.error(node.TYPE) - sys.error("Error parsing arguments in: " + x); - process.exit(1); - })); - } - return ret; -} - -function read_whole_file(filename, cb) { - if (filename == "-") { - var chunks = []; - process.stdin.setEncoding('utf-8'); - process.stdin.on('data', function (chunk) { - chunks.push(chunk); - }).on('end', function () { - cb(null, chunks.join("")); - }); - process.openStdin(); - } else { - fs.readFile(filename, "utf-8", cb); - } -} - -function time_it(name, cont) { - var t1 = new Date().getTime(); - var ret = cont(); - if (ARGS.stats) { - var spent = new Date().getTime() - t1; - if (STATS[name]) STATS[name] += spent; - else STATS[name] = spent; - } - return ret; -} diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/async/LICENSE b/node_modules/handlebars/node_modules/uglify-js/node_modules/async/LICENSE deleted file mode 100644 index b7f9d50..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/async/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2010 Caolan McMahon - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/async/README.md b/node_modules/handlebars/node_modules/uglify-js/node_modules/async/README.md deleted file mode 100644 index 951f76e..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/async/README.md +++ /dev/null @@ -1,1425 +0,0 @@ -# Async.js - -Async is a utility module which provides straight-forward, powerful functions -for working with asynchronous JavaScript. Although originally designed for -use with [node.js](http://nodejs.org), it can also be used directly in the -browser. Also supports [component](https://github.com/component/component). - -Async provides around 20 functions that include the usual 'functional' -suspects (map, reduce, filter, each…) as well as some common patterns -for asynchronous control flow (parallel, series, waterfall…). All these -functions assume you follow the node.js convention of providing a single -callback as the last argument of your async function. - - -## Quick Examples - -```javascript -async.map(['file1','file2','file3'], fs.stat, function(err, results){ - // results is now an array of stats for each file -}); - -async.filter(['file1','file2','file3'], fs.exists, function(results){ - // results now equals an array of the existing files -}); - -async.parallel([ - function(){ ... }, - function(){ ... } -], callback); - -async.series([ - function(){ ... }, - function(){ ... } -]); -``` - -There are many more functions available so take a look at the docs below for a -full list. This module aims to be comprehensive, so if you feel anything is -missing please create a GitHub issue for it. - -## Common Pitfalls - -### Binding a context to an iterator - -This section is really about bind, not about async. If you are wondering how to -make async execute your iterators in a given context, or are confused as to why -a method of another library isn't working as an iterator, study this example: - -```js -// Here is a simple object with an (unnecessarily roundabout) squaring method -var AsyncSquaringLibrary = { - squareExponent: 2, - square: function(number, callback){ - var result = Math.pow(number, this.squareExponent); - setTimeout(function(){ - callback(null, result); - }, 200); - } -}; - -async.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){ - // result is [NaN, NaN, NaN] - // This fails because the `this.squareExponent` expression in the square - // function is not evaluated in the context of AsyncSquaringLibrary, and is - // therefore undefined. -}); - -async.map([1, 2, 3], AsyncSquaringLibrary.square.bind(AsyncSquaringLibrary), function(err, result){ - // result is [1, 4, 9] - // With the help of bind we can attach a context to the iterator before - // passing it to async. Now the square function will be executed in its - // 'home' AsyncSquaringLibrary context and the value of `this.squareExponent` - // will be as expected. -}); -``` - -## Download - -The source is available for download from -[GitHub](http://github.com/caolan/async). -Alternatively, you can install using Node Package Manager (npm): - - npm install async - -__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 29.6kb Uncompressed - -## In the Browser - -So far it's been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage: - -```html - - -``` - -## Documentation - -### Collections - -* [each](#each) -* [eachSeries](#eachSeries) -* [eachLimit](#eachLimit) -* [map](#map) -* [mapSeries](#mapSeries) -* [mapLimit](#mapLimit) -* [filter](#filter) -* [filterSeries](#filterSeries) -* [reject](#reject) -* [rejectSeries](#rejectSeries) -* [reduce](#reduce) -* [reduceRight](#reduceRight) -* [detect](#detect) -* [detectSeries](#detectSeries) -* [sortBy](#sortBy) -* [some](#some) -* [every](#every) -* [concat](#concat) -* [concatSeries](#concatSeries) - -### Control Flow - -* [series](#series) -* [parallel](#parallel) -* [parallelLimit](#parallellimittasks-limit-callback) -* [whilst](#whilst) -* [doWhilst](#doWhilst) -* [until](#until) -* [doUntil](#doUntil) -* [forever](#forever) -* [waterfall](#waterfall) -* [compose](#compose) -* [applyEach](#applyEach) -* [applyEachSeries](#applyEachSeries) -* [queue](#queue) -* [cargo](#cargo) -* [auto](#auto) -* [iterator](#iterator) -* [apply](#apply) -* [nextTick](#nextTick) -* [times](#times) -* [timesSeries](#timesSeries) - -### Utils - -* [memoize](#memoize) -* [unmemoize](#unmemoize) -* [log](#log) -* [dir](#dir) -* [noConflict](#noConflict) - - -## Collections - - - -### each(arr, iterator, callback) - -Applies an iterator function to each item in an array, in parallel. -The iterator is called with an item from the list and a callback for when it -has finished. If the iterator passes an error to this callback, the main -callback for the each function is immediately called with the error. - -Note, that since this function applies the iterator to each item in parallel -there is no guarantee that the iterator functions will complete in order. - -__Arguments__ - -* arr - An array to iterate over. -* iterator(item, callback) - A function to apply to each item in the array. - The iterator is passed a callback(err) which must be called once it has - completed. If no error has occured, the callback should be run without - arguments or with an explicit null argument. -* callback(err) - A callback which is called after all the iterator functions - have finished, or an error has occurred. - -__Example__ - -```js -// assuming openFiles is an array of file names and saveFile is a function -// to save the modified contents of that file: - -async.each(openFiles, saveFile, function(err){ - // if any of the saves produced an error, err would equal that error -}); -``` - ---------------------------------------- - - - -### eachSeries(arr, iterator, callback) - -The same as each only the iterator is applied to each item in the array in -series. The next iterator is only called once the current one has completed -processing. This means the iterator functions will complete in order. - - ---------------------------------------- - - - -### eachLimit(arr, limit, iterator, callback) - -The same as each only no more than "limit" iterators will be simultaneously -running at any time. - -Note that the items are not processed in batches, so there is no guarantee that - the first "limit" iterator functions will complete before any others are -started. - -__Arguments__ - -* arr - An array to iterate over. -* limit - The maximum number of iterators to run at any time. -* iterator(item, callback) - A function to apply to each item in the array. - The iterator is passed a callback(err) which must be called once it has - completed. If no error has occured, the callback should be run without - arguments or with an explicit null argument. -* callback(err) - A callback which is called after all the iterator functions - have finished, or an error has occurred. - -__Example__ - -```js -// Assume documents is an array of JSON objects and requestApi is a -// function that interacts with a rate-limited REST api. - -async.eachLimit(documents, 20, requestApi, function(err){ - // if any of the saves produced an error, err would equal that error -}); -``` - ---------------------------------------- - - -### map(arr, iterator, callback) - -Produces a new array of values by mapping each value in the given array through -the iterator function. The iterator is called with an item from the array and a -callback for when it has finished processing. The callback takes 2 arguments, -an error and the transformed item from the array. If the iterator passes an -error to this callback, the main callback for the map function is immediately -called with the error. - -Note, that since this function applies the iterator to each item in parallel -there is no guarantee that the iterator functions will complete in order, however -the results array will be in the same order as the original array. - -__Arguments__ - -* arr - An array to iterate over. -* iterator(item, callback) - A function to apply to each item in the array. - The iterator is passed a callback(err, transformed) which must be called once - it has completed with an error (which can be null) and a transformed item. -* callback(err, results) - A callback which is called after all the iterator - functions have finished, or an error has occurred. Results is an array of the - transformed items from the original array. - -__Example__ - -```js -async.map(['file1','file2','file3'], fs.stat, function(err, results){ - // results is now an array of stats for each file -}); -``` - ---------------------------------------- - - -### mapSeries(arr, iterator, callback) - -The same as map only the iterator is applied to each item in the array in -series. The next iterator is only called once the current one has completed -processing. The results array will be in the same order as the original. - - ---------------------------------------- - - -### mapLimit(arr, limit, iterator, callback) - -The same as map only no more than "limit" iterators will be simultaneously -running at any time. - -Note that the items are not processed in batches, so there is no guarantee that - the first "limit" iterator functions will complete before any others are -started. - -__Arguments__ - -* arr - An array to iterate over. -* limit - The maximum number of iterators to run at any time. -* iterator(item, callback) - A function to apply to each item in the array. - The iterator is passed a callback(err, transformed) which must be called once - it has completed with an error (which can be null) and a transformed item. -* callback(err, results) - A callback which is called after all the iterator - functions have finished, or an error has occurred. Results is an array of the - transformed items from the original array. - -__Example__ - -```js -async.mapLimit(['file1','file2','file3'], 1, fs.stat, function(err, results){ - // results is now an array of stats for each file -}); -``` - ---------------------------------------- - - -### filter(arr, iterator, callback) - -__Alias:__ select - -Returns a new array of all the values which pass an async truth test. -_The callback for each iterator call only accepts a single argument of true or -false, it does not accept an error argument first!_ This is in-line with the -way node libraries work with truth tests like fs.exists. This operation is -performed in parallel, but the results array will be in the same order as the -original. - -__Arguments__ - -* arr - An array to iterate over. -* iterator(item, callback) - A truth test to apply to each item in the array. - The iterator is passed a callback(truthValue) which must be called with a - boolean argument once it has completed. -* callback(results) - A callback which is called after all the iterator - functions have finished. - -__Example__ - -```js -async.filter(['file1','file2','file3'], fs.exists, function(results){ - // results now equals an array of the existing files -}); -``` - ---------------------------------------- - - -### filterSeries(arr, iterator, callback) - -__alias:__ selectSeries - -The same as filter only the iterator is applied to each item in the array in -series. The next iterator is only called once the current one has completed -processing. The results array will be in the same order as the original. - ---------------------------------------- - - -### reject(arr, iterator, callback) - -The opposite of filter. Removes values that pass an async truth test. - ---------------------------------------- - - -### rejectSeries(arr, iterator, callback) - -The same as reject, only the iterator is applied to each item in the array -in series. - - ---------------------------------------- - - -### reduce(arr, memo, iterator, callback) - -__aliases:__ inject, foldl - -Reduces a list of values into a single value using an async iterator to return -each successive step. Memo is the initial state of the reduction. This -function only operates in series. For performance reasons, it may make sense to -split a call to this function into a parallel map, then use the normal -Array.prototype.reduce on the results. This function is for situations where -each step in the reduction needs to be async, if you can get the data before -reducing it then it's probably a good idea to do so. - -__Arguments__ - -* arr - An array to iterate over. -* memo - The initial state of the reduction. -* iterator(memo, item, callback) - A function applied to each item in the - array to produce the next step in the reduction. The iterator is passed a - callback(err, reduction) which accepts an optional error as its first - argument, and the state of the reduction as the second. If an error is - passed to the callback, the reduction is stopped and the main callback is - immediately called with the error. -* callback(err, result) - A callback which is called after all the iterator - functions have finished. Result is the reduced value. - -__Example__ - -```js -async.reduce([1,2,3], 0, function(memo, item, callback){ - // pointless async: - process.nextTick(function(){ - callback(null, memo + item) - }); -}, function(err, result){ - // result is now equal to the last value of memo, which is 6 -}); -``` - ---------------------------------------- - - -### reduceRight(arr, memo, iterator, callback) - -__Alias:__ foldr - -Same as reduce, only operates on the items in the array in reverse order. - - ---------------------------------------- - - -### detect(arr, iterator, callback) - -Returns the first value in a list that passes an async truth test. The -iterator is applied in parallel, meaning the first iterator to return true will -fire the detect callback with that result. That means the result might not be -the first item in the original array (in terms of order) that passes the test. - -If order within the original array is important then look at detectSeries. - -__Arguments__ - -* arr - An array to iterate over. -* iterator(item, callback) - A truth test to apply to each item in the array. - The iterator is passed a callback(truthValue) which must be called with a - boolean argument once it has completed. -* callback(result) - A callback which is called as soon as any iterator returns - true, or after all the iterator functions have finished. Result will be - the first item in the array that passes the truth test (iterator) or the - value undefined if none passed. - -__Example__ - -```js -async.detect(['file1','file2','file3'], fs.exists, function(result){ - // result now equals the first file in the list that exists -}); -``` - ---------------------------------------- - - -### detectSeries(arr, iterator, callback) - -The same as detect, only the iterator is applied to each item in the array -in series. This means the result is always the first in the original array (in -terms of array order) that passes the truth test. - - ---------------------------------------- - - -### sortBy(arr, iterator, callback) - -Sorts a list by the results of running each value through an async iterator. - -__Arguments__ - -* arr - An array to iterate over. -* iterator(item, callback) - A function to apply to each item in the array. - The iterator is passed a callback(err, sortValue) which must be called once it - has completed with an error (which can be null) and a value to use as the sort - criteria. -* callback(err, results) - A callback which is called after all the iterator - functions have finished, or an error has occurred. Results is the items from - the original array sorted by the values returned by the iterator calls. - -__Example__ - -```js -async.sortBy(['file1','file2','file3'], function(file, callback){ - fs.stat(file, function(err, stats){ - callback(err, stats.mtime); - }); -}, function(err, results){ - // results is now the original array of files sorted by - // modified date -}); -``` - ---------------------------------------- - - -### some(arr, iterator, callback) - -__Alias:__ any - -Returns true if at least one element in the array satisfies an async test. -_The callback for each iterator call only accepts a single argument of true or -false, it does not accept an error argument first!_ This is in-line with the -way node libraries work with truth tests like fs.exists. Once any iterator -call returns true, the main callback is immediately called. - -__Arguments__ - -* arr - An array to iterate over. -* iterator(item, callback) - A truth test to apply to each item in the array. - The iterator is passed a callback(truthValue) which must be called with a - boolean argument once it has completed. -* callback(result) - A callback which is called as soon as any iterator returns - true, or after all the iterator functions have finished. Result will be - either true or false depending on the values of the async tests. - -__Example__ - -```js -async.some(['file1','file2','file3'], fs.exists, function(result){ - // if result is true then at least one of the files exists -}); -``` - ---------------------------------------- - - -### every(arr, iterator, callback) - -__Alias:__ all - -Returns true if every element in the array satisfies an async test. -_The callback for each iterator call only accepts a single argument of true or -false, it does not accept an error argument first!_ This is in-line with the -way node libraries work with truth tests like fs.exists. - -__Arguments__ - -* arr - An array to iterate over. -* iterator(item, callback) - A truth test to apply to each item in the array. - The iterator is passed a callback(truthValue) which must be called with a - boolean argument once it has completed. -* callback(result) - A callback which is called after all the iterator - functions have finished. Result will be either true or false depending on - the values of the async tests. - -__Example__ - -```js -async.every(['file1','file2','file3'], fs.exists, function(result){ - // if result is true then every file exists -}); -``` - ---------------------------------------- - - -### concat(arr, iterator, callback) - -Applies an iterator to each item in a list, concatenating the results. Returns the -concatenated list. The iterators are called in parallel, and the results are -concatenated as they return. There is no guarantee that the results array will -be returned in the original order of the arguments passed to the iterator function. - -__Arguments__ - -* arr - An array to iterate over -* iterator(item, callback) - A function to apply to each item in the array. - The iterator is passed a callback(err, results) which must be called once it - has completed with an error (which can be null) and an array of results. -* callback(err, results) - A callback which is called after all the iterator - functions have finished, or an error has occurred. Results is an array containing - the concatenated results of the iterator function. - -__Example__ - -```js -async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ - // files is now a list of filenames that exist in the 3 directories -}); -``` - ---------------------------------------- - - -### concatSeries(arr, iterator, callback) - -Same as async.concat, but executes in series instead of parallel. - - -## Control Flow - - -### series(tasks, [callback]) - -Run an array of functions in series, each one running once the previous -function has completed. If any functions in the series pass an error to its -callback, no more functions are run and the callback for the series is -immediately called with the value of the error. Once the tasks have completed, -the results are passed to the final callback as an array. - -It is also possible to use an object instead of an array. Each property will be -run as a function and the results will be passed to the final callback as an object -instead of an array. This can be a more readable way of handling results from -async.series. - - -__Arguments__ - -* tasks - An array or object containing functions to run, each function is passed - a callback(err, result) it must call on completion with an error (which can - be null) and an optional result value. -* callback(err, results) - An optional callback to run once all the functions - have completed. This function gets a results array (or object) containing all - the result arguments passed to the task callbacks. - -__Example__ - -```js -async.series([ - function(callback){ - // do some stuff ... - callback(null, 'one'); - }, - function(callback){ - // do some more stuff ... - callback(null, 'two'); - } -], -// optional callback -function(err, results){ - // results is now equal to ['one', 'two'] -}); - - -// an example using an object instead of an array -async.series({ - one: function(callback){ - setTimeout(function(){ - callback(null, 1); - }, 200); - }, - two: function(callback){ - setTimeout(function(){ - callback(null, 2); - }, 100); - } -}, -function(err, results) { - // results is now equal to: {one: 1, two: 2} -}); -``` - ---------------------------------------- - - -### parallel(tasks, [callback]) - -Run an array of functions in parallel, without waiting until the previous -function has completed. If any of the functions pass an error to its -callback, the main callback is immediately called with the value of the error. -Once the tasks have completed, the results are passed to the final callback as an -array. - -It is also possible to use an object instead of an array. Each property will be -run as a function and the results will be passed to the final callback as an object -instead of an array. This can be a more readable way of handling results from -async.parallel. - - -__Arguments__ - -* tasks - An array or object containing functions to run, each function is passed - a callback(err, result) it must call on completion with an error (which can - be null) and an optional result value. -* callback(err, results) - An optional callback to run once all the functions - have completed. This function gets a results array (or object) containing all - the result arguments passed to the task callbacks. - -__Example__ - -```js -async.parallel([ - function(callback){ - setTimeout(function(){ - callback(null, 'one'); - }, 200); - }, - function(callback){ - setTimeout(function(){ - callback(null, 'two'); - }, 100); - } -], -// optional callback -function(err, results){ - // the results array will equal ['one','two'] even though - // the second function had a shorter timeout. -}); - - -// an example using an object instead of an array -async.parallel({ - one: function(callback){ - setTimeout(function(){ - callback(null, 1); - }, 200); - }, - two: function(callback){ - setTimeout(function(){ - callback(null, 2); - }, 100); - } -}, -function(err, results) { - // results is now equals to: {one: 1, two: 2} -}); -``` - ---------------------------------------- - - -### parallelLimit(tasks, limit, [callback]) - -The same as parallel only the tasks are executed in parallel with a maximum of "limit" -tasks executing at any time. - -Note that the tasks are not executed in batches, so there is no guarantee that -the first "limit" tasks will complete before any others are started. - -__Arguments__ - -* tasks - An array or object containing functions to run, each function is passed - a callback(err, result) it must call on completion with an error (which can - be null) and an optional result value. -* limit - The maximum number of tasks to run at any time. -* callback(err, results) - An optional callback to run once all the functions - have completed. This function gets a results array (or object) containing all - the result arguments passed to the task callbacks. - ---------------------------------------- - - -### whilst(test, fn, callback) - -Repeatedly call fn, while test returns true. Calls the callback when stopped, -or an error occurs. - -__Arguments__ - -* test() - synchronous truth test to perform before each execution of fn. -* fn(callback) - A function to call each time the test passes. The function is - passed a callback(err) which must be called once it has completed with an - optional error argument. -* callback(err) - A callback which is called after the test fails and repeated - execution of fn has stopped. - -__Example__ - -```js -var count = 0; - -async.whilst( - function () { return count < 5; }, - function (callback) { - count++; - setTimeout(callback, 1000); - }, - function (err) { - // 5 seconds have passed - } -); -``` - ---------------------------------------- - - -### doWhilst(fn, test, callback) - -The post check version of whilst. To reflect the difference in the order of operations `test` and `fn` arguments are switched. `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript. - ---------------------------------------- - - -### until(test, fn, callback) - -Repeatedly call fn, until test returns true. Calls the callback when stopped, -or an error occurs. - -The inverse of async.whilst. - ---------------------------------------- - - -### doUntil(fn, test, callback) - -Like doWhilst except the test is inverted. Note the argument ordering differs from `until`. - ---------------------------------------- - - -### forever(fn, callback) - -Calls the asynchronous function 'fn' repeatedly, in series, indefinitely. -If an error is passed to fn's callback then 'callback' is called with the -error, otherwise it will never be called. - ---------------------------------------- - - -### waterfall(tasks, [callback]) - -Runs an array of functions in series, each passing their results to the next in -the array. However, if any of the functions pass an error to the callback, the -next function is not executed and the main callback is immediately called with -the error. - -__Arguments__ - -* tasks - An array of functions to run, each function is passed a - callback(err, result1, result2, ...) it must call on completion. The first - argument is an error (which can be null) and any further arguments will be - passed as arguments in order to the next task. -* callback(err, [results]) - An optional callback to run once all the functions - have completed. This will be passed the results of the last task's callback. - - - -__Example__ - -```js -async.waterfall([ - function(callback){ - callback(null, 'one', 'two'); - }, - function(arg1, arg2, callback){ - callback(null, 'three'); - }, - function(arg1, callback){ - // arg1 now equals 'three' - callback(null, 'done'); - } -], function (err, result) { - // result now equals 'done' -}); -``` - ---------------------------------------- - -### compose(fn1, fn2...) - -Creates a function which is a composition of the passed asynchronous -functions. Each function consumes the return value of the function that -follows. Composing functions f(), g() and h() would produce the result of -f(g(h())), only this version uses callbacks to obtain the return values. - -Each function is executed with the `this` binding of the composed function. - -__Arguments__ - -* functions... - the asynchronous functions to compose - - -__Example__ - -```js -function add1(n, callback) { - setTimeout(function () { - callback(null, n + 1); - }, 10); -} - -function mul3(n, callback) { - setTimeout(function () { - callback(null, n * 3); - }, 10); -} - -var add1mul3 = async.compose(mul3, add1); - -add1mul3(4, function (err, result) { - // result now equals 15 -}); -``` - ---------------------------------------- - -### applyEach(fns, args..., callback) - -Applies the provided arguments to each function in the array, calling the -callback after all functions have completed. If you only provide the first -argument then it will return a function which lets you pass in the -arguments as if it were a single function call. - -__Arguments__ - -* fns - the asynchronous functions to all call with the same arguments -* args... - any number of separate arguments to pass to the function -* callback - the final argument should be the callback, called when all - functions have completed processing - - -__Example__ - -```js -async.applyEach([enableSearch, updateSchema], 'bucket', callback); - -// partial application example: -async.each( - buckets, - async.applyEach([enableSearch, updateSchema]), - callback -); -``` - ---------------------------------------- - - -### applyEachSeries(arr, iterator, callback) - -The same as applyEach only the functions are applied in series. - ---------------------------------------- - - -### queue(worker, concurrency) - -Creates a queue object with the specified concurrency. Tasks added to the -queue will be processed in parallel (up to the concurrency limit). If all -workers are in progress, the task is queued until one is available. Once -a worker has completed a task, the task's callback is called. - -__Arguments__ - -* worker(task, callback) - An asynchronous function for processing a queued - task, which must call its callback(err) argument when finished, with an - optional error as an argument. -* concurrency - An integer for determining how many worker functions should be - run in parallel. - -__Queue objects__ - -The queue object returned by this function has the following properties and -methods: - -* length() - a function returning the number of items waiting to be processed. -* concurrency - an integer for determining how many worker functions should be - run in parallel. This property can be changed after a queue is created to - alter the concurrency on-the-fly. -* push(task, [callback]) - add a new task to the queue, the callback is called - once the worker has finished processing the task. - instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list. -* unshift(task, [callback]) - add a new task to the front of the queue. -* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued -* empty - a callback that is called when the last item from the queue is given to a worker -* drain - a callback that is called when the last item from the queue has returned from the worker - -__Example__ - -```js -// create a queue object with concurrency 2 - -var q = async.queue(function (task, callback) { - console.log('hello ' + task.name); - callback(); -}, 2); - - -// assign a callback -q.drain = function() { - console.log('all items have been processed'); -} - -// add some items to the queue - -q.push({name: 'foo'}, function (err) { - console.log('finished processing foo'); -}); -q.push({name: 'bar'}, function (err) { - console.log('finished processing bar'); -}); - -// add some items to the queue (batch-wise) - -q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) { - console.log('finished processing bar'); -}); - -// add some items to the front of the queue - -q.unshift({name: 'bar'}, function (err) { - console.log('finished processing bar'); -}); -``` - ---------------------------------------- - - -### cargo(worker, [payload]) - -Creates a cargo object with the specified payload. Tasks added to the -cargo will be processed altogether (up to the payload limit). If the -worker is in progress, the task is queued until it is available. Once -the worker has completed some tasks, each callback of those tasks is called. - -__Arguments__ - -* worker(tasks, callback) - An asynchronous function for processing an array of - queued tasks, which must call its callback(err) argument when finished, with - an optional error as an argument. -* payload - An optional integer for determining how many tasks should be - processed per round; if omitted, the default is unlimited. - -__Cargo objects__ - -The cargo object returned by this function has the following properties and -methods: - -* length() - a function returning the number of items waiting to be processed. -* payload - an integer for determining how many tasks should be - process per round. This property can be changed after a cargo is created to - alter the payload on-the-fly. -* push(task, [callback]) - add a new task to the queue, the callback is called - once the worker has finished processing the task. - instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list. -* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued -* empty - a callback that is called when the last item from the queue is given to a worker -* drain - a callback that is called when the last item from the queue has returned from the worker - -__Example__ - -```js -// create a cargo object with payload 2 - -var cargo = async.cargo(function (tasks, callback) { - for(var i=0; i -### auto(tasks, [callback]) - -Determines the best order for running functions based on their requirements. -Each function can optionally depend on other functions being completed first, -and each function is run as soon as its requirements are satisfied. If any of -the functions pass an error to their callback, that function will not complete -(so any other functions depending on it will not run) and the main callback -will be called immediately with the error. Functions also receive an object -containing the results of functions which have completed so far. - -Note, all functions are called with a results object as a second argument, -so it is unsafe to pass functions in the tasks object which cannot handle the -extra argument. For example, this snippet of code: - -```js -async.auto({ - readData: async.apply(fs.readFile, 'data.txt', 'utf-8') -}, callback); -``` - -will have the effect of calling readFile with the results object as the last -argument, which will fail: - -```js -fs.readFile('data.txt', 'utf-8', cb, {}); -``` - -Instead, wrap the call to readFile in a function which does not forward the -results object: - -```js -async.auto({ - readData: function(cb, results){ - fs.readFile('data.txt', 'utf-8', cb); - } -}, callback); -``` - -__Arguments__ - -* tasks - An object literal containing named functions or an array of - requirements, with the function itself the last item in the array. The key - used for each function or array is used when specifying requirements. The - function receives two arguments: (1) a callback(err, result) which must be - called when finished, passing an error (which can be null) and the result of - the function's execution, and (2) a results object, containing the results of - the previously executed functions. -* callback(err, results) - An optional callback which is called when all the - tasks have been completed. The callback will receive an error as an argument - if any tasks pass an error to their callback. Results will always be passed - but if an error occurred, no other tasks will be performed, and the results - object will only contain partial results. - - -__Example__ - -```js -async.auto({ - get_data: function(callback){ - // async code to get some data - }, - make_folder: function(callback){ - // async code to create a directory to store a file in - // this is run at the same time as getting the data - }, - write_file: ['get_data', 'make_folder', function(callback){ - // once there is some data and the directory exists, - // write the data to a file in the directory - callback(null, filename); - }], - email_link: ['write_file', function(callback, results){ - // once the file is written let's email a link to it... - // results.write_file contains the filename returned by write_file. - }] -}); -``` - -This is a fairly trivial example, but to do this using the basic parallel and -series functions would look like this: - -```js -async.parallel([ - function(callback){ - // async code to get some data - }, - function(callback){ - // async code to create a directory to store a file in - // this is run at the same time as getting the data - } -], -function(err, results){ - async.series([ - function(callback){ - // once there is some data and the directory exists, - // write the data to a file in the directory - }, - function(callback){ - // once the file is written let's email a link to it... - } - ]); -}); -``` - -For a complicated series of async tasks using the auto function makes adding -new tasks much easier and makes the code more readable. - - ---------------------------------------- - - -### iterator(tasks) - -Creates an iterator function which calls the next function in the array, -returning a continuation to call the next one after that. It's also possible to -'peek' the next iterator by doing iterator.next(). - -This function is used internally by the async module but can be useful when -you want to manually control the flow of functions in series. - -__Arguments__ - -* tasks - An array of functions to run. - -__Example__ - -```js -var iterator = async.iterator([ - function(){ sys.p('one'); }, - function(){ sys.p('two'); }, - function(){ sys.p('three'); } -]); - -node> var iterator2 = iterator(); -'one' -node> var iterator3 = iterator2(); -'two' -node> iterator3(); -'three' -node> var nextfn = iterator2.next(); -node> nextfn(); -'three' -``` - ---------------------------------------- - - -### apply(function, arguments..) - -Creates a continuation function with some arguments already applied, a useful -shorthand when combined with other control flow functions. Any arguments -passed to the returned function are added to the arguments originally passed -to apply. - -__Arguments__ - -* function - The function you want to eventually apply all arguments to. -* arguments... - Any number of arguments to automatically apply when the - continuation is called. - -__Example__ - -```js -// using apply - -async.parallel([ - async.apply(fs.writeFile, 'testfile1', 'test1'), - async.apply(fs.writeFile, 'testfile2', 'test2'), -]); - - -// the same process without using apply - -async.parallel([ - function(callback){ - fs.writeFile('testfile1', 'test1', callback); - }, - function(callback){ - fs.writeFile('testfile2', 'test2', callback); - } -]); -``` - -It's possible to pass any number of additional arguments when calling the -continuation: - -```js -node> var fn = async.apply(sys.puts, 'one'); -node> fn('two', 'three'); -one -two -three -``` - ---------------------------------------- - - -### nextTick(callback) - -Calls the callback on a later loop around the event loop. In node.js this just -calls process.nextTick, in the browser it falls back to setImmediate(callback) -if available, otherwise setTimeout(callback, 0), which means other higher priority -events may precede the execution of the callback. - -This is used internally for browser-compatibility purposes. - -__Arguments__ - -* callback - The function to call on a later loop around the event loop. - -__Example__ - -```js -var call_order = []; -async.nextTick(function(){ - call_order.push('two'); - // call_order now equals ['one','two'] -}); -call_order.push('one') -``` - - -### times(n, callback) - -Calls the callback n times and accumulates results in the same manner -you would use with async.map. - -__Arguments__ - -* n - The number of times to run the function. -* callback - The function to call n times. - -__Example__ - -```js -// Pretend this is some complicated async factory -var createUser = function(id, callback) { - callback(null, { - id: 'user' + id - }) -} -// generate 5 users -async.times(5, function(n, next){ - createUser(n, function(err, user) { - next(err, user) - }) -}, function(err, users) { - // we should now have 5 users -}); -``` - - -### timesSeries(n, callback) - -The same as times only the iterator is applied to each item in the array in -series. The next iterator is only called once the current one has completed -processing. The results array will be in the same order as the original. - - -## Utils - - -### memoize(fn, [hasher]) - -Caches the results of an async function. When creating a hash to store function -results against, the callback is omitted from the hash and an optional hash -function can be used. - -The cache of results is exposed as the `memo` property of the function returned -by `memoize`. - -__Arguments__ - -* fn - the function you to proxy and cache results from. -* hasher - an optional function for generating a custom hash for storing - results, it has all the arguments applied to it apart from the callback, and - must be synchronous. - -__Example__ - -```js -var slow_fn = function (name, callback) { - // do something - callback(null, result); -}; -var fn = async.memoize(slow_fn); - -// fn can now be used as if it were slow_fn -fn('some name', function () { - // callback -}); -``` - - -### unmemoize(fn) - -Undoes a memoized function, reverting it to the original, unmemoized -form. Comes handy in tests. - -__Arguments__ - -* fn - the memoized function - - -### log(function, arguments) - -Logs the result of an async function to the console. Only works in node.js or -in browsers that support console.log and console.error (such as FF and Chrome). -If multiple arguments are returned from the async function, console.log is -called on each argument in order. - -__Arguments__ - -* function - The function you want to eventually apply all arguments to. -* arguments... - Any number of arguments to apply to the function. - -__Example__ - -```js -var hello = function(name, callback){ - setTimeout(function(){ - callback(null, 'hello ' + name); - }, 1000); -}; -``` -```js -node> async.log(hello, 'world'); -'hello world' -``` - ---------------------------------------- - - -### dir(function, arguments) - -Logs the result of an async function to the console using console.dir to -display the properties of the resulting object. Only works in node.js or -in browsers that support console.dir and console.error (such as FF and Chrome). -If multiple arguments are returned from the async function, console.dir is -called on each argument in order. - -__Arguments__ - -* function - The function you want to eventually apply all arguments to. -* arguments... - Any number of arguments to apply to the function. - -__Example__ - -```js -var hello = function(name, callback){ - setTimeout(function(){ - callback(null, {hello: name}); - }, 1000); -}; -``` -```js -node> async.dir(hello, 'world'); -{hello: 'world'} -``` - ---------------------------------------- - - -### noConflict() - -Changes the value of async back to its original value, returning a reference to the -async object. diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/async/component.json b/node_modules/handlebars/node_modules/uglify-js/node_modules/async/component.json deleted file mode 100644 index bbb0115..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/async/component.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "async", - "repo": "caolan/async", - "description": "Higher-order functions and common patterns for asynchronous code", - "version": "0.1.23", - "keywords": [], - "dependencies": {}, - "development": {}, - "main": "lib/async.js", - "scripts": [ "lib/async.js" ] -} diff --git a/node_modules/handlebars/node_modules/uglify-js/node_modules/async/package.json b/node_modules/handlebars/node_modules/uglify-js/node_modules/async/package.json deleted file mode 100644 index 3bc4c47..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/node_modules/async/package.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "name": "async", - "description": "Higher-order functions and common patterns for asynchronous code", - "main": "./lib/async", - "author": { - "name": "Caolan McMahon" - }, - "version": "0.2.10", - "repository": { - "type": "git", - "url": "git+https://github.com/caolan/async.git" - }, - "bugs": { - "url": "https://github.com/caolan/async/issues" - }, - "licenses": [ - { - "type": "MIT", - "url": "https://github.com/caolan/async/raw/master/LICENSE" - } - ], - "devDependencies": { - "nodeunit": ">0.0.0", - "uglify-js": "1.2.x", - "nodelint": ">0.0.0" - }, - "jam": { - "main": "lib/async.js", - "include": [ - "lib/async.js", - "README.md", - "LICENSE" - ] - }, - "scripts": { - "test": "nodeunit test/test-async.js" - }, - "_id": "async@0.2.10", - "dist": { - "shasum": "b6bbe0b0674b9d719708ca38de8c237cb526c3d1", - "tarball": "http://registry.npmjs.org/async/-/async-0.2.10.tgz" - }, - "_from": "async@>=0.2.6 <0.3.0", - "_npmVersion": "1.3.2", - "_npmUser": { - "name": "caolan", - "email": "caolan.mcmahon@gmail.com" - }, - "maintainers": [ - { - "name": "caolan", - "email": "caolan@caolanmcmahon.com" - } - ], - "directories": {}, - "_shasum": "b6bbe0b0674b9d719708ca38de8c237cb526c3d1", - "_resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "readme": "# Async.js\n\nAsync is a utility module which provides straight-forward, powerful functions\nfor working with asynchronous JavaScript. Although originally designed for\nuse with [node.js](http://nodejs.org), it can also be used directly in the\nbrowser. Also supports [component](https://github.com/component/component).\n\nAsync provides around 20 functions that include the usual 'functional'\nsuspects (map, reduce, filter, each…) as well as some common patterns\nfor asynchronous control flow (parallel, series, waterfall…). All these\nfunctions assume you follow the node.js convention of providing a single\ncallback as the last argument of your async function.\n\n\n## Quick Examples\n\n```javascript\nasync.map(['file1','file2','file3'], fs.stat, function(err, results){\n // results is now an array of stats for each file\n});\n\nasync.filter(['file1','file2','file3'], fs.exists, function(results){\n // results now equals an array of the existing files\n});\n\nasync.parallel([\n function(){ ... },\n function(){ ... }\n], callback);\n\nasync.series([\n function(){ ... },\n function(){ ... }\n]);\n```\n\nThere are many more functions available so take a look at the docs below for a\nfull list. This module aims to be comprehensive, so if you feel anything is\nmissing please create a GitHub issue for it.\n\n## Common Pitfalls\n\n### Binding a context to an iterator\n\nThis section is really about bind, not about async. If you are wondering how to\nmake async execute your iterators in a given context, or are confused as to why\na method of another library isn't working as an iterator, study this example:\n\n```js\n// Here is a simple object with an (unnecessarily roundabout) squaring method\nvar AsyncSquaringLibrary = {\n squareExponent: 2,\n square: function(number, callback){ \n var result = Math.pow(number, this.squareExponent);\n setTimeout(function(){\n callback(null, result);\n }, 200);\n }\n};\n\nasync.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){\n // result is [NaN, NaN, NaN]\n // This fails because the `this.squareExponent` expression in the square\n // function is not evaluated in the context of AsyncSquaringLibrary, and is\n // therefore undefined.\n});\n\nasync.map([1, 2, 3], AsyncSquaringLibrary.square.bind(AsyncSquaringLibrary), function(err, result){\n // result is [1, 4, 9]\n // With the help of bind we can attach a context to the iterator before\n // passing it to async. Now the square function will be executed in its \n // 'home' AsyncSquaringLibrary context and the value of `this.squareExponent`\n // will be as expected.\n});\n```\n\n## Download\n\nThe source is available for download from\n[GitHub](http://github.com/caolan/async).\nAlternatively, you can install using Node Package Manager (npm):\n\n npm install async\n\n__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 29.6kb Uncompressed\n\n## In the Browser\n\nSo far it's been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage:\n\n```html\n\n\n```\n\n## Documentation\n\n### Collections\n\n* [each](#each)\n* [eachSeries](#eachSeries)\n* [eachLimit](#eachLimit)\n* [map](#map)\n* [mapSeries](#mapSeries)\n* [mapLimit](#mapLimit)\n* [filter](#filter)\n* [filterSeries](#filterSeries)\n* [reject](#reject)\n* [rejectSeries](#rejectSeries)\n* [reduce](#reduce)\n* [reduceRight](#reduceRight)\n* [detect](#detect)\n* [detectSeries](#detectSeries)\n* [sortBy](#sortBy)\n* [some](#some)\n* [every](#every)\n* [concat](#concat)\n* [concatSeries](#concatSeries)\n\n### Control Flow\n\n* [series](#series)\n* [parallel](#parallel)\n* [parallelLimit](#parallellimittasks-limit-callback)\n* [whilst](#whilst)\n* [doWhilst](#doWhilst)\n* [until](#until)\n* [doUntil](#doUntil)\n* [forever](#forever)\n* [waterfall](#waterfall)\n* [compose](#compose)\n* [applyEach](#applyEach)\n* [applyEachSeries](#applyEachSeries)\n* [queue](#queue)\n* [cargo](#cargo)\n* [auto](#auto)\n* [iterator](#iterator)\n* [apply](#apply)\n* [nextTick](#nextTick)\n* [times](#times)\n* [timesSeries](#timesSeries)\n\n### Utils\n\n* [memoize](#memoize)\n* [unmemoize](#unmemoize)\n* [log](#log)\n* [dir](#dir)\n* [noConflict](#noConflict)\n\n\n## Collections\n\n\n\n### each(arr, iterator, callback)\n\nApplies an iterator function to each item in an array, in parallel.\nThe iterator is called with an item from the list and a callback for when it\nhas finished. If the iterator passes an error to this callback, the main\ncallback for the each function is immediately called with the error.\n\nNote, that since this function applies the iterator to each item in parallel\nthere is no guarantee that the iterator functions will complete in order.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err) which must be called once it has \n completed. If no error has occured, the callback should be run without \n arguments or with an explicit null argument.\n* callback(err) - A callback which is called after all the iterator functions\n have finished, or an error has occurred.\n\n__Example__\n\n```js\n// assuming openFiles is an array of file names and saveFile is a function\n// to save the modified contents of that file:\n\nasync.each(openFiles, saveFile, function(err){\n // if any of the saves produced an error, err would equal that error\n});\n```\n\n---------------------------------------\n\n\n\n### eachSeries(arr, iterator, callback)\n\nThe same as each only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. This means the iterator functions will complete in order.\n\n\n---------------------------------------\n\n\n\n### eachLimit(arr, limit, iterator, callback)\n\nThe same as each only no more than \"limit\" iterators will be simultaneously \nrunning at any time.\n\nNote that the items are not processed in batches, so there is no guarantee that\n the first \"limit\" iterator functions will complete before any others are \nstarted.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* limit - The maximum number of iterators to run at any time.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err) which must be called once it has \n completed. If no error has occured, the callback should be run without \n arguments or with an explicit null argument.\n* callback(err) - A callback which is called after all the iterator functions\n have finished, or an error has occurred.\n\n__Example__\n\n```js\n// Assume documents is an array of JSON objects and requestApi is a\n// function that interacts with a rate-limited REST api.\n\nasync.eachLimit(documents, 20, requestApi, function(err){\n // if any of the saves produced an error, err would equal that error\n});\n```\n\n---------------------------------------\n\n\n### map(arr, iterator, callback)\n\nProduces a new array of values by mapping each value in the given array through\nthe iterator function. The iterator is called with an item from the array and a\ncallback for when it has finished processing. The callback takes 2 arguments, \nan error and the transformed item from the array. If the iterator passes an\nerror to this callback, the main callback for the map function is immediately\ncalled with the error.\n\nNote, that since this function applies the iterator to each item in parallel\nthere is no guarantee that the iterator functions will complete in order, however\nthe results array will be in the same order as the original array.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, transformed) which must be called once \n it has completed with an error (which can be null) and a transformed item.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array of the\n transformed items from the original array.\n\n__Example__\n\n```js\nasync.map(['file1','file2','file3'], fs.stat, function(err, results){\n // results is now an array of stats for each file\n});\n```\n\n---------------------------------------\n\n\n### mapSeries(arr, iterator, callback)\n\nThe same as map only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n\n---------------------------------------\n\n\n### mapLimit(arr, limit, iterator, callback)\n\nThe same as map only no more than \"limit\" iterators will be simultaneously \nrunning at any time.\n\nNote that the items are not processed in batches, so there is no guarantee that\n the first \"limit\" iterator functions will complete before any others are \nstarted.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* limit - The maximum number of iterators to run at any time.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, transformed) which must be called once \n it has completed with an error (which can be null) and a transformed item.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array of the\n transformed items from the original array.\n\n__Example__\n\n```js\nasync.mapLimit(['file1','file2','file3'], 1, fs.stat, function(err, results){\n // results is now an array of stats for each file\n});\n```\n\n---------------------------------------\n\n\n### filter(arr, iterator, callback)\n\n__Alias:__ select\n\nReturns a new array of all the values which pass an async truth test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like fs.exists. This operation is\nperformed in parallel, but the results array will be in the same order as the\noriginal.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(results) - A callback which is called after all the iterator\n functions have finished.\n\n__Example__\n\n```js\nasync.filter(['file1','file2','file3'], fs.exists, function(results){\n // results now equals an array of the existing files\n});\n```\n\n---------------------------------------\n\n\n### filterSeries(arr, iterator, callback)\n\n__alias:__ selectSeries\n\nThe same as filter only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n---------------------------------------\n\n\n### reject(arr, iterator, callback)\n\nThe opposite of filter. Removes values that pass an async truth test.\n\n---------------------------------------\n\n\n### rejectSeries(arr, iterator, callback)\n\nThe same as reject, only the iterator is applied to each item in the array\nin series.\n\n\n---------------------------------------\n\n\n### reduce(arr, memo, iterator, callback)\n\n__aliases:__ inject, foldl\n\nReduces a list of values into a single value using an async iterator to return\neach successive step. Memo is the initial state of the reduction. This\nfunction only operates in series. For performance reasons, it may make sense to\nsplit a call to this function into a parallel map, then use the normal\nArray.prototype.reduce on the results. This function is for situations where\neach step in the reduction needs to be async, if you can get the data before\nreducing it then it's probably a good idea to do so.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* memo - The initial state of the reduction.\n* iterator(memo, item, callback) - A function applied to each item in the\n array to produce the next step in the reduction. The iterator is passed a\n callback(err, reduction) which accepts an optional error as its first \n argument, and the state of the reduction as the second. If an error is \n passed to the callback, the reduction is stopped and the main callback is \n immediately called with the error.\n* callback(err, result) - A callback which is called after all the iterator\n functions have finished. Result is the reduced value.\n\n__Example__\n\n```js\nasync.reduce([1,2,3], 0, function(memo, item, callback){\n // pointless async:\n process.nextTick(function(){\n callback(null, memo + item)\n });\n}, function(err, result){\n // result is now equal to the last value of memo, which is 6\n});\n```\n\n---------------------------------------\n\n\n### reduceRight(arr, memo, iterator, callback)\n\n__Alias:__ foldr\n\nSame as reduce, only operates on the items in the array in reverse order.\n\n\n---------------------------------------\n\n\n### detect(arr, iterator, callback)\n\nReturns the first value in a list that passes an async truth test. The\niterator is applied in parallel, meaning the first iterator to return true will\nfire the detect callback with that result. That means the result might not be\nthe first item in the original array (in terms of order) that passes the test.\n\nIf order within the original array is important then look at detectSeries.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(result) - A callback which is called as soon as any iterator returns\n true, or after all the iterator functions have finished. Result will be\n the first item in the array that passes the truth test (iterator) or the\n value undefined if none passed.\n\n__Example__\n\n```js\nasync.detect(['file1','file2','file3'], fs.exists, function(result){\n // result now equals the first file in the list that exists\n});\n```\n\n---------------------------------------\n\n\n### detectSeries(arr, iterator, callback)\n\nThe same as detect, only the iterator is applied to each item in the array\nin series. This means the result is always the first in the original array (in\nterms of array order) that passes the truth test.\n\n\n---------------------------------------\n\n\n### sortBy(arr, iterator, callback)\n\nSorts a list by the results of running each value through an async iterator.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, sortValue) which must be called once it\n has completed with an error (which can be null) and a value to use as the sort\n criteria.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is the items from\n the original array sorted by the values returned by the iterator calls.\n\n__Example__\n\n```js\nasync.sortBy(['file1','file2','file3'], function(file, callback){\n fs.stat(file, function(err, stats){\n callback(err, stats.mtime);\n });\n}, function(err, results){\n // results is now the original array of files sorted by\n // modified date\n});\n```\n\n---------------------------------------\n\n\n### some(arr, iterator, callback)\n\n__Alias:__ any\n\nReturns true if at least one element in the array satisfies an async test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like fs.exists. Once any iterator\ncall returns true, the main callback is immediately called.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(result) - A callback which is called as soon as any iterator returns\n true, or after all the iterator functions have finished. Result will be\n either true or false depending on the values of the async tests.\n\n__Example__\n\n```js\nasync.some(['file1','file2','file3'], fs.exists, function(result){\n // if result is true then at least one of the files exists\n});\n```\n\n---------------------------------------\n\n\n### every(arr, iterator, callback)\n\n__Alias:__ all\n\nReturns true if every element in the array satisfies an async test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like fs.exists.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(result) - A callback which is called after all the iterator\n functions have finished. Result will be either true or false depending on\n the values of the async tests.\n\n__Example__\n\n```js\nasync.every(['file1','file2','file3'], fs.exists, function(result){\n // if result is true then every file exists\n});\n```\n\n---------------------------------------\n\n\n### concat(arr, iterator, callback)\n\nApplies an iterator to each item in a list, concatenating the results. Returns the\nconcatenated list. The iterators are called in parallel, and the results are\nconcatenated as they return. There is no guarantee that the results array will\nbe returned in the original order of the arguments passed to the iterator function.\n\n__Arguments__\n\n* arr - An array to iterate over\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, results) which must be called once it \n has completed with an error (which can be null) and an array of results.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array containing\n the concatenated results of the iterator function.\n\n__Example__\n\n```js\nasync.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){\n // files is now a list of filenames that exist in the 3 directories\n});\n```\n\n---------------------------------------\n\n\n### concatSeries(arr, iterator, callback)\n\nSame as async.concat, but executes in series instead of parallel.\n\n\n## Control Flow\n\n\n### series(tasks, [callback])\n\nRun an array of functions in series, each one running once the previous\nfunction has completed. If any functions in the series pass an error to its\ncallback, no more functions are run and the callback for the series is\nimmediately called with the value of the error. Once the tasks have completed,\nthe results are passed to the final callback as an array.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final callback as an object\ninstead of an array. This can be a more readable way of handling results from\nasync.series.\n\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed\n a callback(err, result) it must call on completion with an error (which can\n be null) and an optional result value.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the task callbacks.\n\n__Example__\n\n```js\nasync.series([\n function(callback){\n // do some stuff ...\n callback(null, 'one');\n },\n function(callback){\n // do some more stuff ...\n callback(null, 'two');\n }\n],\n// optional callback\nfunction(err, results){\n // results is now equal to ['one', 'two']\n});\n\n\n// an example using an object instead of an array\nasync.series({\n one: function(callback){\n setTimeout(function(){\n callback(null, 1);\n }, 200);\n },\n two: function(callback){\n setTimeout(function(){\n callback(null, 2);\n }, 100);\n }\n},\nfunction(err, results) {\n // results is now equal to: {one: 1, two: 2}\n});\n```\n\n---------------------------------------\n\n\n### parallel(tasks, [callback])\n\nRun an array of functions in parallel, without waiting until the previous\nfunction has completed. If any of the functions pass an error to its\ncallback, the main callback is immediately called with the value of the error.\nOnce the tasks have completed, the results are passed to the final callback as an\narray.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final callback as an object\ninstead of an array. This can be a more readable way of handling results from\nasync.parallel.\n\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed \n a callback(err, result) it must call on completion with an error (which can\n be null) and an optional result value.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the task callbacks.\n\n__Example__\n\n```js\nasync.parallel([\n function(callback){\n setTimeout(function(){\n callback(null, 'one');\n }, 200);\n },\n function(callback){\n setTimeout(function(){\n callback(null, 'two');\n }, 100);\n }\n],\n// optional callback\nfunction(err, results){\n // the results array will equal ['one','two'] even though\n // the second function had a shorter timeout.\n});\n\n\n// an example using an object instead of an array\nasync.parallel({\n one: function(callback){\n setTimeout(function(){\n callback(null, 1);\n }, 200);\n },\n two: function(callback){\n setTimeout(function(){\n callback(null, 2);\n }, 100);\n }\n},\nfunction(err, results) {\n // results is now equals to: {one: 1, two: 2}\n});\n```\n\n---------------------------------------\n\n\n### parallelLimit(tasks, limit, [callback])\n\nThe same as parallel only the tasks are executed in parallel with a maximum of \"limit\" \ntasks executing at any time.\n\nNote that the tasks are not executed in batches, so there is no guarantee that \nthe first \"limit\" tasks will complete before any others are started.\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed \n a callback(err, result) it must call on completion with an error (which can\n be null) and an optional result value.\n* limit - The maximum number of tasks to run at any time.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the task callbacks.\n\n---------------------------------------\n\n\n### whilst(test, fn, callback)\n\nRepeatedly call fn, while test returns true. Calls the callback when stopped,\nor an error occurs.\n\n__Arguments__\n\n* test() - synchronous truth test to perform before each execution of fn.\n* fn(callback) - A function to call each time the test passes. The function is\n passed a callback(err) which must be called once it has completed with an \n optional error argument.\n* callback(err) - A callback which is called after the test fails and repeated\n execution of fn has stopped.\n\n__Example__\n\n```js\nvar count = 0;\n\nasync.whilst(\n function () { return count < 5; },\n function (callback) {\n count++;\n setTimeout(callback, 1000);\n },\n function (err) {\n // 5 seconds have passed\n }\n);\n```\n\n---------------------------------------\n\n\n### doWhilst(fn, test, callback)\n\nThe post check version of whilst. To reflect the difference in the order of operations `test` and `fn` arguments are switched. `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.\n\n---------------------------------------\n\n\n### until(test, fn, callback)\n\nRepeatedly call fn, until test returns true. Calls the callback when stopped,\nor an error occurs.\n\nThe inverse of async.whilst.\n\n---------------------------------------\n\n\n### doUntil(fn, test, callback)\n\nLike doWhilst except the test is inverted. Note the argument ordering differs from `until`.\n\n---------------------------------------\n\n\n### forever(fn, callback)\n\nCalls the asynchronous function 'fn' repeatedly, in series, indefinitely.\nIf an error is passed to fn's callback then 'callback' is called with the\nerror, otherwise it will never be called.\n\n---------------------------------------\n\n\n### waterfall(tasks, [callback])\n\nRuns an array of functions in series, each passing their results to the next in\nthe array. However, if any of the functions pass an error to the callback, the\nnext function is not executed and the main callback is immediately called with\nthe error.\n\n__Arguments__\n\n* tasks - An array of functions to run, each function is passed a \n callback(err, result1, result2, ...) it must call on completion. The first\n argument is an error (which can be null) and any further arguments will be \n passed as arguments in order to the next task.\n* callback(err, [results]) - An optional callback to run once all the functions\n have completed. This will be passed the results of the last task's callback.\n\n\n\n__Example__\n\n```js\nasync.waterfall([\n function(callback){\n callback(null, 'one', 'two');\n },\n function(arg1, arg2, callback){\n callback(null, 'three');\n },\n function(arg1, callback){\n // arg1 now equals 'three'\n callback(null, 'done');\n }\n], function (err, result) {\n // result now equals 'done' \n});\n```\n\n---------------------------------------\n\n### compose(fn1, fn2...)\n\nCreates a function which is a composition of the passed asynchronous\nfunctions. Each function consumes the return value of the function that\nfollows. Composing functions f(), g() and h() would produce the result of\nf(g(h())), only this version uses callbacks to obtain the return values.\n\nEach function is executed with the `this` binding of the composed function.\n\n__Arguments__\n\n* functions... - the asynchronous functions to compose\n\n\n__Example__\n\n```js\nfunction add1(n, callback) {\n setTimeout(function () {\n callback(null, n + 1);\n }, 10);\n}\n\nfunction mul3(n, callback) {\n setTimeout(function () {\n callback(null, n * 3);\n }, 10);\n}\n\nvar add1mul3 = async.compose(mul3, add1);\n\nadd1mul3(4, function (err, result) {\n // result now equals 15\n});\n```\n\n---------------------------------------\n\n### applyEach(fns, args..., callback)\n\nApplies the provided arguments to each function in the array, calling the\ncallback after all functions have completed. If you only provide the first\nargument then it will return a function which lets you pass in the\narguments as if it were a single function call.\n\n__Arguments__\n\n* fns - the asynchronous functions to all call with the same arguments\n* args... - any number of separate arguments to pass to the function\n* callback - the final argument should be the callback, called when all\n functions have completed processing\n\n\n__Example__\n\n```js\nasync.applyEach([enableSearch, updateSchema], 'bucket', callback);\n\n// partial application example:\nasync.each(\n buckets,\n async.applyEach([enableSearch, updateSchema]),\n callback\n);\n```\n\n---------------------------------------\n\n\n### applyEachSeries(arr, iterator, callback)\n\nThe same as applyEach only the functions are applied in series.\n\n---------------------------------------\n\n\n### queue(worker, concurrency)\n\nCreates a queue object with the specified concurrency. Tasks added to the\nqueue will be processed in parallel (up to the concurrency limit). If all\nworkers are in progress, the task is queued until one is available. Once\na worker has completed a task, the task's callback is called.\n\n__Arguments__\n\n* worker(task, callback) - An asynchronous function for processing a queued\n task, which must call its callback(err) argument when finished, with an \n optional error as an argument.\n* concurrency - An integer for determining how many worker functions should be\n run in parallel.\n\n__Queue objects__\n\nThe queue object returned by this function has the following properties and\nmethods:\n\n* length() - a function returning the number of items waiting to be processed.\n* concurrency - an integer for determining how many worker functions should be\n run in parallel. This property can be changed after a queue is created to\n alter the concurrency on-the-fly.\n* push(task, [callback]) - add a new task to the queue, the callback is called\n once the worker has finished processing the task.\n instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.\n* unshift(task, [callback]) - add a new task to the front of the queue.\n* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued\n* empty - a callback that is called when the last item from the queue is given to a worker\n* drain - a callback that is called when the last item from the queue has returned from the worker\n\n__Example__\n\n```js\n// create a queue object with concurrency 2\n\nvar q = async.queue(function (task, callback) {\n console.log('hello ' + task.name);\n callback();\n}, 2);\n\n\n// assign a callback\nq.drain = function() {\n console.log('all items have been processed');\n}\n\n// add some items to the queue\n\nq.push({name: 'foo'}, function (err) {\n console.log('finished processing foo');\n});\nq.push({name: 'bar'}, function (err) {\n console.log('finished processing bar');\n});\n\n// add some items to the queue (batch-wise)\n\nq.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) {\n console.log('finished processing bar');\n});\n\n// add some items to the front of the queue\n\nq.unshift({name: 'bar'}, function (err) {\n console.log('finished processing bar');\n});\n```\n\n---------------------------------------\n\n\n### cargo(worker, [payload])\n\nCreates a cargo object with the specified payload. Tasks added to the\ncargo will be processed altogether (up to the payload limit). If the\nworker is in progress, the task is queued until it is available. Once\nthe worker has completed some tasks, each callback of those tasks is called.\n\n__Arguments__\n\n* worker(tasks, callback) - An asynchronous function for processing an array of\n queued tasks, which must call its callback(err) argument when finished, with \n an optional error as an argument.\n* payload - An optional integer for determining how many tasks should be\n processed per round; if omitted, the default is unlimited.\n\n__Cargo objects__\n\nThe cargo object returned by this function has the following properties and\nmethods:\n\n* length() - a function returning the number of items waiting to be processed.\n* payload - an integer for determining how many tasks should be\n process per round. This property can be changed after a cargo is created to\n alter the payload on-the-fly.\n* push(task, [callback]) - add a new task to the queue, the callback is called\n once the worker has finished processing the task.\n instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.\n* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued\n* empty - a callback that is called when the last item from the queue is given to a worker\n* drain - a callback that is called when the last item from the queue has returned from the worker\n\n__Example__\n\n```js\n// create a cargo object with payload 2\n\nvar cargo = async.cargo(function (tasks, callback) {\n for(var i=0; i\n### auto(tasks, [callback])\n\nDetermines the best order for running functions based on their requirements.\nEach function can optionally depend on other functions being completed first,\nand each function is run as soon as its requirements are satisfied. If any of\nthe functions pass an error to their callback, that function will not complete\n(so any other functions depending on it will not run) and the main callback\nwill be called immediately with the error. Functions also receive an object\ncontaining the results of functions which have completed so far.\n\nNote, all functions are called with a results object as a second argument, \nso it is unsafe to pass functions in the tasks object which cannot handle the\nextra argument. For example, this snippet of code:\n\n```js\nasync.auto({\n readData: async.apply(fs.readFile, 'data.txt', 'utf-8')\n}, callback);\n```\n\nwill have the effect of calling readFile with the results object as the last\nargument, which will fail:\n\n```js\nfs.readFile('data.txt', 'utf-8', cb, {});\n```\n\nInstead, wrap the call to readFile in a function which does not forward the \nresults object:\n\n```js\nasync.auto({\n readData: function(cb, results){\n fs.readFile('data.txt', 'utf-8', cb);\n }\n}, callback);\n```\n\n__Arguments__\n\n* tasks - An object literal containing named functions or an array of\n requirements, with the function itself the last item in the array. The key\n used for each function or array is used when specifying requirements. The \n function receives two arguments: (1) a callback(err, result) which must be \n called when finished, passing an error (which can be null) and the result of \n the function's execution, and (2) a results object, containing the results of\n the previously executed functions.\n* callback(err, results) - An optional callback which is called when all the\n tasks have been completed. The callback will receive an error as an argument\n if any tasks pass an error to their callback. Results will always be passed\n\tbut if an error occurred, no other tasks will be performed, and the results\n\tobject will only contain partial results.\n \n\n__Example__\n\n```js\nasync.auto({\n get_data: function(callback){\n // async code to get some data\n },\n make_folder: function(callback){\n // async code to create a directory to store a file in\n // this is run at the same time as getting the data\n },\n write_file: ['get_data', 'make_folder', function(callback){\n // once there is some data and the directory exists,\n // write the data to a file in the directory\n callback(null, filename);\n }],\n email_link: ['write_file', function(callback, results){\n // once the file is written let's email a link to it...\n // results.write_file contains the filename returned by write_file.\n }]\n});\n```\n\nThis is a fairly trivial example, but to do this using the basic parallel and\nseries functions would look like this:\n\n```js\nasync.parallel([\n function(callback){\n // async code to get some data\n },\n function(callback){\n // async code to create a directory to store a file in\n // this is run at the same time as getting the data\n }\n],\nfunction(err, results){\n async.series([\n function(callback){\n // once there is some data and the directory exists,\n // write the data to a file in the directory\n },\n function(callback){\n // once the file is written let's email a link to it...\n }\n ]);\n});\n```\n\nFor a complicated series of async tasks using the auto function makes adding\nnew tasks much easier and makes the code more readable.\n\n\n---------------------------------------\n\n\n### iterator(tasks)\n\nCreates an iterator function which calls the next function in the array,\nreturning a continuation to call the next one after that. It's also possible to\n'peek' the next iterator by doing iterator.next().\n\nThis function is used internally by the async module but can be useful when\nyou want to manually control the flow of functions in series.\n\n__Arguments__\n\n* tasks - An array of functions to run.\n\n__Example__\n\n```js\nvar iterator = async.iterator([\n function(){ sys.p('one'); },\n function(){ sys.p('two'); },\n function(){ sys.p('three'); }\n]);\n\nnode> var iterator2 = iterator();\n'one'\nnode> var iterator3 = iterator2();\n'two'\nnode> iterator3();\n'three'\nnode> var nextfn = iterator2.next();\nnode> nextfn();\n'three'\n```\n\n---------------------------------------\n\n\n### apply(function, arguments..)\n\nCreates a continuation function with some arguments already applied, a useful\nshorthand when combined with other control flow functions. Any arguments\npassed to the returned function are added to the arguments originally passed\nto apply.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to automatically apply when the\n continuation is called.\n\n__Example__\n\n```js\n// using apply\n\nasync.parallel([\n async.apply(fs.writeFile, 'testfile1', 'test1'),\n async.apply(fs.writeFile, 'testfile2', 'test2'),\n]);\n\n\n// the same process without using apply\n\nasync.parallel([\n function(callback){\n fs.writeFile('testfile1', 'test1', callback);\n },\n function(callback){\n fs.writeFile('testfile2', 'test2', callback);\n }\n]);\n```\n\nIt's possible to pass any number of additional arguments when calling the\ncontinuation:\n\n```js\nnode> var fn = async.apply(sys.puts, 'one');\nnode> fn('two', 'three');\none\ntwo\nthree\n```\n\n---------------------------------------\n\n\n### nextTick(callback)\n\nCalls the callback on a later loop around the event loop. In node.js this just\ncalls process.nextTick, in the browser it falls back to setImmediate(callback)\nif available, otherwise setTimeout(callback, 0), which means other higher priority\nevents may precede the execution of the callback.\n\nThis is used internally for browser-compatibility purposes.\n\n__Arguments__\n\n* callback - The function to call on a later loop around the event loop.\n\n__Example__\n\n```js\nvar call_order = [];\nasync.nextTick(function(){\n call_order.push('two');\n // call_order now equals ['one','two']\n});\ncall_order.push('one')\n```\n\n\n### times(n, callback)\n\nCalls the callback n times and accumulates results in the same manner\nyou would use with async.map.\n\n__Arguments__\n\n* n - The number of times to run the function.\n* callback - The function to call n times.\n\n__Example__\n\n```js\n// Pretend this is some complicated async factory\nvar createUser = function(id, callback) {\n callback(null, {\n id: 'user' + id\n })\n}\n// generate 5 users\nasync.times(5, function(n, next){\n createUser(n, function(err, user) {\n next(err, user)\n })\n}, function(err, users) {\n // we should now have 5 users\n});\n```\n\n\n### timesSeries(n, callback)\n\nThe same as times only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n\n## Utils\n\n\n### memoize(fn, [hasher])\n\nCaches the results of an async function. When creating a hash to store function\nresults against, the callback is omitted from the hash and an optional hash\nfunction can be used.\n\nThe cache of results is exposed as the `memo` property of the function returned\nby `memoize`.\n\n__Arguments__\n\n* fn - the function you to proxy and cache results from.\n* hasher - an optional function for generating a custom hash for storing\n results, it has all the arguments applied to it apart from the callback, and\n must be synchronous.\n\n__Example__\n\n```js\nvar slow_fn = function (name, callback) {\n // do something\n callback(null, result);\n};\nvar fn = async.memoize(slow_fn);\n\n// fn can now be used as if it were slow_fn\nfn('some name', function () {\n // callback\n});\n```\n\n\n### unmemoize(fn)\n\nUndoes a memoized function, reverting it to the original, unmemoized\nform. Comes handy in tests.\n\n__Arguments__\n\n* fn - the memoized function\n\n\n### log(function, arguments)\n\nLogs the result of an async function to the console. Only works in node.js or\nin browsers that support console.log and console.error (such as FF and Chrome).\nIf multiple arguments are returned from the async function, console.log is\ncalled on each argument in order.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to apply to the function.\n\n__Example__\n\n```js\nvar hello = function(name, callback){\n setTimeout(function(){\n callback(null, 'hello ' + name);\n }, 1000);\n};\n```\n```js\nnode> async.log(hello, 'world');\n'hello world'\n```\n\n---------------------------------------\n\n\n### dir(function, arguments)\n\nLogs the result of an async function to the console using console.dir to\ndisplay the properties of the resulting object. Only works in node.js or\nin browsers that support console.dir and console.error (such as FF and Chrome).\nIf multiple arguments are returned from the async function, console.dir is\ncalled on each argument in order.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to apply to the function.\n\n__Example__\n\n```js\nvar hello = function(name, callback){\n setTimeout(function(){\n callback(null, {hello: name});\n }, 1000);\n};\n```\n```js\nnode> async.dir(hello, 'world');\n{hello: 'world'}\n```\n\n---------------------------------------\n\n\n### noConflict()\n\nChanges the value of async back to its original value, returning a reference to the\nasync object.\n", - "readmeFilename": "README.md", - "homepage": "https://github.com/caolan/async#readme" -} diff --git a/node_modules/handlebars/node_modules/uglify-js/package.json b/node_modules/handlebars/node_modules/uglify-js/package.json deleted file mode 100644 index 636a6cd..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/package.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "uglify-js", - "description": "JavaScript parser, mangler/compressor and beautifier toolkit", - "homepage": "http://lisperator.net/uglifyjs", - "main": "tools/node.js", - "version": "2.3.6", - "engines": { - "node": ">=0.4.0" - }, - "maintainers": [ - { - "name": "Mihai Bazon", - "email": "mihai.bazon@gmail.com", - "url": "http://lisperator.net/" - } - ], - "repository": { - "type": "git", - "url": "git+https://github.com/mishoo/UglifyJS2.git" - }, - "dependencies": { - "async": "~0.2.6", - "source-map": "~0.1.7", - "optimist": "~0.3.5" - }, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "scripts": { - "test": "node test/run-tests.js" - }, - "readme": "UglifyJS 2\n==========\n[![Build Status](https://travis-ci.org/mishoo/UglifyJS2.png)](https://travis-ci.org/mishoo/UglifyJS2)\n\nUglifyJS is a JavaScript parser, minifier, compressor or beautifier toolkit.\n\nThis page documents the command line utility. For\n[API and internals documentation see my website](http://lisperator.net/uglifyjs/).\nThere's also an\n[in-browser online demo](http://lisperator.net/uglifyjs/#demo) (for Firefox,\nChrome and probably Safari).\n\nInstall\n-------\n\nFirst make sure you have installed the latest version of [node.js](http://nodejs.org/)\n(You may need to restart your computer after this step).\n\nFrom NPM for use as a command line app:\n\n npm install uglify-js -g\n\nFrom NPM for programmatic use:\n\n npm install uglify-js\n\nFrom Git:\n\n git clone git://github.com/mishoo/UglifyJS2.git\n cd UglifyJS2\n npm link .\n\nUsage\n-----\n\n uglifyjs [input files] [options]\n\nUglifyJS2 can take multiple input files. It's recommended that you pass the\ninput files first, then pass the options. UglifyJS will parse input files\nin sequence and apply any compression options. The files are parsed in the\nsame global scope, that is, a reference from a file to some\nvariable/function declared in another file will be matched properly.\n\nIf you want to read from STDIN instead, pass a single dash instead of input\nfiles.\n\nThe available options are:\n\n --source-map Specify an output file where to generate source map.\n [string]\n --source-map-root The path to the original source to be included in the\n source map. [string]\n --source-map-url The path to the source map to be added in //@\n sourceMappingURL. Defaults to the value passed with\n --source-map. [string]\n --in-source-map Input source map, useful if you're compressing JS that was\n generated from some other original code.\n --screw-ie8 Pass this flag if you don't care about full compliance with\n Internet Explorer 6-8 quirks (by default UglifyJS will try\n to be IE-proof).\n -p, --prefix Skip prefix for original filenames that appear in source\n maps. For example -p 3 will drop 3 directories from file\n names and ensure they are relative paths.\n -o, --output Output file (default STDOUT).\n -b, --beautify Beautify output/specify output options. [string]\n -m, --mangle Mangle names/pass mangler options. [string]\n -r, --reserved Reserved names to exclude from mangling.\n -c, --compress Enable compressor/pass compressor options. Pass options\n like -c hoist_vars=false,if_return=false. Use -c with no\n argument to use the default compression options. [string]\n -d, --define Global definitions [string]\n --comments Preserve copyright comments in the output. By default this\n works like Google Closure, keeping JSDoc-style comments\n that contain \"@license\" or \"@preserve\". You can optionally\n pass one of the following arguments to this flag:\n - \"all\" to keep all comments\n - a valid JS regexp (needs to start with a slash) to keep\n only comments that match.\n Note that currently not *all* comments can be kept when\n compression is on, because of dead code removal or\n cascading statements into sequences. [string]\n --stats Display operations run time on STDERR. [boolean]\n --acorn Use Acorn for parsing. [boolean]\n --spidermonkey Assume input files are SpiderMonkey AST format (as JSON).\n [boolean]\n --self Build itself (UglifyJS2) as a library (implies\n --wrap=UglifyJS --export-all) [boolean]\n --wrap Embed everything in a big function, making the “exports”\n and “global” variables available. You need to pass an\n argument to this option to specify the name that your\n module will take when included in, say, a browser.\n [string]\n --export-all Only used when --wrap, this tells UglifyJS to add code to\n automatically export all globals. [boolean]\n --lint Display some scope warnings [boolean]\n -v, --verbose Verbose [boolean]\n -V, --version Print version number and exit. [boolean]\n\nSpecify `--output` (`-o`) to declare the output file. Otherwise the output\ngoes to STDOUT.\n\n## Source map options\n\nUglifyJS2 can generate a source map file, which is highly useful for\ndebugging your compressed JavaScript. To get a source map, pass\n`--source-map output.js.map` (full path to the file where you want the\nsource map dumped).\n\nAdditionally you might need `--source-map-root` to pass the URL where the\noriginal files can be found. In case you are passing full paths to input\nfiles to UglifyJS, you can use `--prefix` (`-p`) to specify the number of\ndirectories to drop from the path prefix when declaring files in the source\nmap.\n\nFor example:\n\n uglifyjs /home/doe/work/foo/src/js/file1.js \\\n /home/doe/work/foo/src/js/file2.js \\\n -o foo.min.js \\\n --source-map foo.min.js.map \\\n --source-map-root http://foo.com/src \\\n -p 5 -c -m\n\nThe above will compress and mangle `file1.js` and `file2.js`, will drop the\noutput in `foo.min.js` and the source map in `foo.min.js.map`. The source\nmapping will refer to `http://foo.com/src/js/file1.js` and\n`http://foo.com/src/js/file2.js` (in fact it will list `http://foo.com/src`\nas the source map root, and the original files as `js/file1.js` and\n`js/file2.js`).\n\n### Composed source map\n\nWhen you're compressing JS code that was output by a compiler such as\nCoffeeScript, mapping to the JS code won't be too helpful. Instead, you'd\nlike to map back to the original code (i.e. CoffeeScript). UglifyJS has an\noption to take an input source map. Assuming you have a mapping from\nCoffeeScript → compiled JS, UglifyJS can generate a map from CoffeeScript →\ncompressed JS by mapping every token in the compiled JS to its original\nlocation.\n\nTo use this feature you need to pass `--in-source-map\n/path/to/input/source.map`. Normally the input source map should also point\nto the file containing the generated JS, so if that's correct you can omit\ninput files from the command line.\n\n## Mangler options\n\nTo enable the mangler you need to pass `--mangle` (`-m`). The following\n(comma-separated) options are supported:\n\n- `sort` — to assign shorter names to most frequently used variables. This\n saves a few hundred bytes on jQuery before gzip, but the output is\n _bigger_ after gzip (and seems to happen for other libraries I tried it\n on) therefore it's not enabled by default.\n\n- `toplevel` — mangle names declared in the toplevel scope (disabled by\n default).\n\n- `eval` — mangle names visible in scopes where `eval` or `when` are used\n (disabled by default).\n\nWhen mangling is enabled but you want to prevent certain names from being\nmangled, you can declare those names with `--reserved` (`-r`) — pass a\ncomma-separated list of names. For example:\n\n uglifyjs ... -m -r '$,require,exports'\n\nto prevent the `require`, `exports` and `$` names from being changed.\n\n## Compressor options\n\nYou need to pass `--compress` (`-c`) to enable the compressor. Optionally\nyou can pass a comma-separated list of options. Options are in the form\n`foo=bar`, or just `foo` (the latter implies a boolean option that you want\nto set `true`; it's effectively a shortcut for `foo=true`).\n\n- `sequences` -- join consecutive simple statements using the comma operator\n- `properties` -- rewrite property access using the dot notation, for\n example `foo[\"bar\"] → foo.bar`\n- `dead_code` -- remove unreachable code\n- `drop_debugger` -- remove `debugger;` statements\n- `unsafe` (default: false) -- apply \"unsafe\" transformations (discussion below)\n- `conditionals` -- apply optimizations for `if`-s and conditional\n expressions\n- `comparisons` -- apply certain optimizations to binary nodes, for example:\n `!(a <= b) → a > b` (only when `unsafe`), attempts to negate binary nodes,\n e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.\n- `evaluate` -- attempt to evaluate constant expressions\n- `booleans` -- various optimizations for boolean context, for example `!!a\n ? b : c → a ? b : c`\n- `loops` -- optimizations for `do`, `while` and `for` loops when we can\n statically determine the condition\n- `unused` -- drop unreferenced functions and variables\n- `hoist_funs` -- hoist function declarations\n- `hoist_vars` (default: false) -- hoist `var` declarations (this is `false`\n by default because it seems to increase the size of the output in general)\n- `if_return` -- optimizations for if/return and if/continue\n- `join_vars` -- join consecutive `var` statements\n- `cascade` -- small optimization for sequences, transform `x, x` into `x`\n and `x = something(), x` into `x = something()`\n- `warnings` -- display warnings when dropping unreachable code or unused\n declarations etc.\n\n### The `unsafe` option\n\nIt enables some transformations that *might* break code logic in certain\ncontrived cases, but should be fine for most code. You might want to try it\non your own code, it should reduce the minified size. Here's what happens\nwhen this flag is on:\n\n- `new Array(1, 2, 3)` or `Array(1, 2, 3)` → `[1, 2, 3 ]`\n- `new Object()` → `{}`\n- `String(exp)` or `exp.toString()` → `\"\" + exp`\n- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new`\n- `typeof foo == \"undefined\"` → `foo === void 0`\n- `void 0` → `\"undefined\"` (if there is a variable named \"undefined\" in\n scope; we do it because the variable name will be mangled, typically\n reduced to a single character).\n\n### Conditional compilation\n\nYou can use the `--define` (`-d`) switch in order to declare global\nvariables that UglifyJS will assume to be constants (unless defined in\nscope). For example if you pass `--define DEBUG=false` then, coupled with\ndead code removal UglifyJS will discard the following from the output:\n```javascript\nif (DEBUG) {\n\tconsole.log(\"debug stuff\");\n}\n```\n\nUglifyJS will warn about the condition being always false and about dropping\nunreachable code; for now there is no option to turn off only this specific\nwarning, you can pass `warnings=false` to turn off *all* warnings.\n\nAnother way of doing that is to declare your globals as constants in a\nseparate file and include it into the build. For example you can have a\n`build/defines.js` file with the following:\n```javascript\nconst DEBUG = false;\nconst PRODUCTION = true;\n// etc.\n```\n\nand build your code like this:\n\n uglifyjs build/defines.js js/foo.js js/bar.js... -c\n\nUglifyJS will notice the constants and, since they cannot be altered, it\nwill evaluate references to them to the value itself and drop unreachable\ncode as usual. The possible downside of this approach is that the build\nwill contain the `const` declarations.\n\n\n## Beautifier options\n\nThe code generator tries to output shortest code possible by default. In\ncase you want beautified output, pass `--beautify` (`-b`). Optionally you\ncan pass additional arguments that control the code output:\n\n- `beautify` (default `true`) -- whether to actually beautify the output.\n Passing `-b` will set this to true, but you might need to pass `-b` even\n when you want to generate minified code, in order to specify additional\n arguments, so you can use `-b beautify=false` to override it.\n- `indent-level` (default 4)\n- `indent-start` (default 0) -- prefix all lines by that many spaces\n- `quote-keys` (default `false`) -- pass `true` to quote all keys in literal\n objects\n- `space-colon` (default `true`) -- insert a space after the colon signs\n- `ascii-only` (default `false`) -- escape Unicode characters in strings and\n regexps\n- `inline-script` (default `false`) -- escape the slash in occurrences of\n `=2.3.0 <2.4.0" -} diff --git a/node_modules/handlebars/node_modules/uglify-js/test/compress/arrays.js b/node_modules/handlebars/node_modules/uglify-js/test/compress/arrays.js deleted file mode 100644 index 10fe6eb..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/test/compress/arrays.js +++ /dev/null @@ -1,12 +0,0 @@ -holes_and_undefined: { - input: { - x = [1, 2, undefined]; - y = [1, , 2, ]; - z = [1, undefined, 3]; - } - expect: { - x=[1,2,void 0]; - y=[1,,2]; - z=[1,void 0,3]; - } -} diff --git a/node_modules/handlebars/node_modules/uglify-js/test/compress/blocks.js b/node_modules/handlebars/node_modules/uglify-js/test/compress/blocks.js deleted file mode 100644 index 8372adf..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/test/compress/blocks.js +++ /dev/null @@ -1,49 +0,0 @@ -remove_blocks: { - input: { - {;} - foo(); - {}; - { - {}; - }; - bar(); - {} - } - expect: { - foo(); - bar(); - } -} - -keep_some_blocks: { - input: { - // 1. - if (foo) { - {{{}}} - if (bar) { baz(); } - {{}} - } else { - stuff(); - } - - // 2. - if (foo) { - for (var i = 0; i < 5; ++i) - if (bar) baz(); - } else { - stuff(); - } - } - expect: { - // 1. - if (foo) { - if (bar) baz(); - } else stuff(); - - // 2. - if (foo) { - for (var i = 0; i < 5; ++i) - if (bar) baz(); - } else stuff(); - } -} diff --git a/node_modules/handlebars/node_modules/uglify-js/test/compress/conditionals.js b/node_modules/handlebars/node_modules/uglify-js/test/compress/conditionals.js deleted file mode 100644 index dc2bb67..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/test/compress/conditionals.js +++ /dev/null @@ -1,143 +0,0 @@ -ifs_1: { - options = { - conditionals: true - }; - input: { - if (foo) bar(); - if (!foo); else bar(); - if (foo); else bar(); - if (foo); else; - } - expect: { - foo&&bar(); - foo&&bar(); - foo||bar(); - foo; - } -} - -ifs_2: { - options = { - conditionals: true - }; - input: { - if (foo) { - x(); - } else if (bar) { - y(); - } else if (baz) { - z(); - } - - if (foo) { - x(); - } else if (bar) { - y(); - } else if (baz) { - z(); - } else { - t(); - } - } - expect: { - foo ? x() : bar ? y() : baz && z(); - foo ? x() : bar ? y() : baz ? z() : t(); - } -} - -ifs_3_should_warn: { - options = { - conditionals : true, - dead_code : true, - evaluate : true, - booleans : true - }; - input: { - if (x && !(x + "1") && y) { // 1 - var qq; - foo(); - } else { - bar(); - } - - if (x || !!(x + "1") || y) { // 2 - foo(); - } else { - var jj; - bar(); - } - } - expect: { - var qq; bar(); // 1 - var jj; foo(); // 2 - } -} - -ifs_4: { - options = { - conditionals: true - }; - input: { - if (foo && bar) { - x(foo)[10].bar.baz = something(); - } else - x(foo)[10].bar.baz = something_else(); - } - expect: { - x(foo)[10].bar.baz = (foo && bar) ? something() : something_else(); - } -} - -ifs_5: { - options = { - if_return: true, - conditionals: true, - comparisons: true, - }; - input: { - function f() { - if (foo) return; - bar(); - baz(); - } - function g() { - if (foo) return; - if (bar) return; - if (baz) return; - if (baa) return; - a(); - b(); - } - } - expect: { - function f() { - if (!foo) { - bar(); - baz(); - } - } - function g() { - if (!(foo || bar || baz || baa)) { - a(); - b(); - } - } - } -} - -ifs_6: { - options = { - conditionals: true, - comparisons: true - }; - input: { - if (!foo && !bar && !baz && !boo) { - x = 10; - } else { - x = 20; - } - } - expect: { - x = foo || bar || baz || boo ? 20 : 10; - } -} diff --git a/node_modules/handlebars/node_modules/uglify-js/test/compress/dead-code.js b/node_modules/handlebars/node_modules/uglify-js/test/compress/dead-code.js deleted file mode 100644 index 0fd066e..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/test/compress/dead-code.js +++ /dev/null @@ -1,89 +0,0 @@ -dead_code_1: { - options = { - dead_code: true - }; - input: { - function f() { - a(); - b(); - x = 10; - return; - if (x) { - y(); - } - } - } - expect: { - function f() { - a(); - b(); - x = 10; - return; - } - } -} - -dead_code_2_should_warn: { - options = { - dead_code: true - }; - input: { - function f() { - g(); - x = 10; - throw "foo"; - // completely discarding the `if` would introduce some - // bugs. UglifyJS v1 doesn't deal with this issue; in v2 - // we copy any declarations to the upper scope. - if (x) { - y(); - var x; - function g(){}; - // but nested declarations should not be kept. - (function(){ - var q; - function y(){}; - })(); - } - } - } - expect: { - function f() { - g(); - x = 10; - throw "foo"; - var x; - function g(){}; - } - } -} - -dead_code_constant_boolean_should_warn_more: { - options = { - dead_code : true, - loops : true, - booleans : true, - conditionals : true, - evaluate : true - }; - input: { - while (!((foo && bar) || (x + "0"))) { - console.log("unreachable"); - var foo; - function bar() {} - } - for (var x = 10; x && (y || x) && (!typeof x); ++x) { - asdf(); - foo(); - var moo; - } - } - expect: { - var foo; - function bar() {} - // nothing for the while - // as for the for, it should keep: - var x = 10; - var moo; - } -} diff --git a/node_modules/handlebars/node_modules/uglify-js/test/compress/debugger.js b/node_modules/handlebars/node_modules/uglify-js/test/compress/debugger.js deleted file mode 100644 index 7c27073..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/test/compress/debugger.js +++ /dev/null @@ -1,24 +0,0 @@ -keep_debugger: { - options = { - drop_debugger: false - }; - input: { - debugger; - } - expect: { - debugger; - } -} - -drop_debugger: { - options = { - drop_debugger: true - }; - input: { - debugger; - if (foo) debugger; - } - expect: { - if (foo); - } -} diff --git a/node_modules/handlebars/node_modules/uglify-js/test/compress/drop-unused.js b/node_modules/handlebars/node_modules/uglify-js/test/compress/drop-unused.js deleted file mode 100644 index bf5cd29..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/test/compress/drop-unused.js +++ /dev/null @@ -1,97 +0,0 @@ -unused_funarg_1: { - options = { unused: true }; - input: { - function f(a, b, c, d, e) { - return a + b; - } - } - expect: { - function f(a, b) { - return a + b; - } - } -} - -unused_funarg_2: { - options = { unused: true }; - input: { - function f(a, b, c, d, e) { - return a + c; - } - } - expect: { - function f(a, b, c) { - return a + c; - } - } -} - -unused_nested_function: { - options = { unused: true }; - input: { - function f(x, y) { - function g() { - something(); - } - return x + y; - } - }; - expect: { - function f(x, y) { - return x + y; - } - } -} - -unused_circular_references_1: { - options = { unused: true }; - input: { - function f(x, y) { - // circular reference - function g() { - return h(); - } - function h() { - return g(); - } - return x + y; - } - }; - expect: { - function f(x, y) { - return x + y; - } - } -} - -unused_circular_references_2: { - options = { unused: true }; - input: { - function f(x, y) { - var foo = 1, bar = baz, baz = foo + bar, qwe = moo(); - return x + y; - } - }; - expect: { - function f(x, y) { - moo(); // keeps side effect - return x + y; - } - } -} - -unused_circular_references_3: { - options = { unused: true }; - input: { - function f(x, y) { - var g = function() { return h() }; - var h = function() { return g() }; - return x + y; - } - }; - expect: { - function f(x, y) { - return x + y; - } - } -} diff --git a/node_modules/handlebars/node_modules/uglify-js/test/compress/issue-105.js b/node_modules/handlebars/node_modules/uglify-js/test/compress/issue-105.js deleted file mode 100644 index ca17adb..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/test/compress/issue-105.js +++ /dev/null @@ -1,25 +0,0 @@ -typeof_eq_undefined: { - options = { - comparisons: true - }; - input: { a = typeof b.c != "undefined" } - expect: { a = "undefined" != typeof b.c } -} - -typeof_eq_undefined_unsafe: { - options = { - comparisons: true, - unsafe: true - }; - input: { a = typeof b.c != "undefined" } - expect: { a = void 0 !== b.c } -} - -typeof_eq_undefined_unsafe2: { - options = { - comparisons: true, - unsafe: true - }; - input: { a = "undefined" != typeof b.c } - expect: { a = void 0 !== b.c } -} diff --git a/node_modules/handlebars/node_modules/uglify-js/test/compress/issue-12.js b/node_modules/handlebars/node_modules/uglify-js/test/compress/issue-12.js deleted file mode 100644 index bf87d5c..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/test/compress/issue-12.js +++ /dev/null @@ -1,11 +0,0 @@ -keep_name_of_getter: { - options = { unused: true }; - input: { a = { get foo () {} } } - expect: { a = { get foo () {} } } -} - -keep_name_of_setter: { - options = { unused: true }; - input: { a = { set foo () {} } } - expect: { a = { set foo () {} } } -} diff --git a/node_modules/handlebars/node_modules/uglify-js/test/compress/issue-143.js b/node_modules/handlebars/node_modules/uglify-js/test/compress/issue-143.js deleted file mode 100644 index 4c79790..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/test/compress/issue-143.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * There was an incorrect sort behaviour documented in issue #143: - * (x = f(…)) <= x → x >= (x = f(…)) - * - * For example, let the equation be: - * (a = parseInt('100')) <= a - * - * If a was an integer and has the value of 99, - * (a = parseInt('100')) <= a → 100 <= 100 → true - * - * When transformed incorrectly: - * a >= (a = parseInt('100')) → 99 >= 100 → false - */ - -tranformation_sort_order_equal: { - options = { - comparisons: true, - }; - - input: { (a = parseInt('100')) == a } - expect: { (a = parseInt('100')) == a } -} - -tranformation_sort_order_unequal: { - options = { - comparisons: true, - }; - - input: { (a = parseInt('100')) != a } - expect: { (a = parseInt('100')) != a } -} - -tranformation_sort_order_lesser_or_equal: { - options = { - comparisons: true, - }; - - input: { (a = parseInt('100')) <= a } - expect: { (a = parseInt('100')) <= a } -} -tranformation_sort_order_greater_or_equal: { - options = { - comparisons: true, - }; - - input: { (a = parseInt('100')) >= a } - expect: { (a = parseInt('100')) >= a } -} \ No newline at end of file diff --git a/node_modules/handlebars/node_modules/uglify-js/test/compress/issue-22.js b/node_modules/handlebars/node_modules/uglify-js/test/compress/issue-22.js deleted file mode 100644 index a8b7bc6..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/test/compress/issue-22.js +++ /dev/null @@ -1,17 +0,0 @@ -return_with_no_value_in_if_body: { - options = { conditionals: true }; - input: { - function foo(bar) { - if (bar) { - return; - } else { - return 1; - } - } - } - expect: { - function foo (bar) { - return bar ? void 0 : 1; - } - } -} diff --git a/node_modules/handlebars/node_modules/uglify-js/test/compress/issue-44.js b/node_modules/handlebars/node_modules/uglify-js/test/compress/issue-44.js deleted file mode 100644 index 7a972f9..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/test/compress/issue-44.js +++ /dev/null @@ -1,31 +0,0 @@ -issue_44_valid_ast_1: { - options = { unused: true }; - input: { - function a(b) { - for (var i = 0, e = b.qoo(); ; i++) {} - } - } - expect: { - function a(b) { - var i = 0; - for (b.qoo(); ; i++); - } - } -} - -issue_44_valid_ast_2: { - options = { unused: true }; - input: { - function a(b) { - if (foo) for (var i = 0, e = b.qoo(); ; i++) {} - } - } - expect: { - function a(b) { - if (foo) { - var i = 0; - for (b.qoo(); ; i++); - } - } - } -} diff --git a/node_modules/handlebars/node_modules/uglify-js/test/compress/issue-59.js b/node_modules/handlebars/node_modules/uglify-js/test/compress/issue-59.js deleted file mode 100644 index 82b3880..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/test/compress/issue-59.js +++ /dev/null @@ -1,30 +0,0 @@ -keep_continue: { - options = { - dead_code: true, - evaluate: true - }; - input: { - while (a) { - if (b) { - switch (true) { - case c(): - d(); - } - continue; - } - f(); - } - } - expect: { - while (a) { - if (b) { - switch (true) { - case c(): - d(); - } - continue; - } - f(); - } - } -} diff --git a/node_modules/handlebars/node_modules/uglify-js/test/compress/labels.js b/node_modules/handlebars/node_modules/uglify-js/test/compress/labels.js deleted file mode 100644 index 044b7a7..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/test/compress/labels.js +++ /dev/null @@ -1,163 +0,0 @@ -labels_1: { - options = { if_return: true, conditionals: true, dead_code: true }; - input: { - out: { - if (foo) break out; - console.log("bar"); - } - }; - expect: { - foo || console.log("bar"); - } -} - -labels_2: { - options = { if_return: true, conditionals: true, dead_code: true }; - input: { - out: { - if (foo) print("stuff"); - else break out; - console.log("here"); - } - }; - expect: { - if (foo) { - print("stuff"); - console.log("here"); - } - } -} - -labels_3: { - options = { if_return: true, conditionals: true, dead_code: true }; - input: { - for (var i = 0; i < 5; ++i) { - if (i < 3) continue; - console.log(i); - } - }; - expect: { - for (var i = 0; i < 5; ++i) - i < 3 || console.log(i); - } -} - -labels_4: { - options = { if_return: true, conditionals: true, dead_code: true }; - input: { - out: for (var i = 0; i < 5; ++i) { - if (i < 3) continue out; - console.log(i); - } - }; - expect: { - for (var i = 0; i < 5; ++i) - i < 3 || console.log(i); - } -} - -labels_5: { - options = { if_return: true, conditionals: true, dead_code: true }; - // should keep the break-s in the following - input: { - while (foo) { - if (bar) break; - console.log("foo"); - } - out: while (foo) { - if (bar) break out; - console.log("foo"); - } - }; - expect: { - while (foo) { - if (bar) break; - console.log("foo"); - } - out: while (foo) { - if (bar) break out; - console.log("foo"); - } - } -} - -labels_6: { - input: { - out: break out; - }; - expect: {} -} - -labels_7: { - options = { if_return: true, conditionals: true, dead_code: true }; - input: { - while (foo) { - x(); - y(); - continue; - } - }; - expect: { - while (foo) { - x(); - y(); - } - } -} - -labels_8: { - options = { if_return: true, conditionals: true, dead_code: true }; - input: { - while (foo) { - x(); - y(); - break; - } - }; - expect: { - while (foo) { - x(); - y(); - break; - } - } -} - -labels_9: { - options = { if_return: true, conditionals: true, dead_code: true }; - input: { - out: while (foo) { - x(); - y(); - continue out; - z(); - k(); - } - }; - expect: { - while (foo) { - x(); - y(); - } - } -} - -labels_10: { - options = { if_return: true, conditionals: true, dead_code: true }; - input: { - out: while (foo) { - x(); - y(); - break out; - z(); - k(); - } - }; - expect: { - out: while (foo) { - x(); - y(); - break out; - } - } -} diff --git a/node_modules/handlebars/node_modules/uglify-js/test/compress/loops.js b/node_modules/handlebars/node_modules/uglify-js/test/compress/loops.js deleted file mode 100644 index cdf1f04..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/test/compress/loops.js +++ /dev/null @@ -1,123 +0,0 @@ -while_becomes_for: { - options = { loops: true }; - input: { - while (foo()) bar(); - } - expect: { - for (; foo(); ) bar(); - } -} - -drop_if_break_1: { - options = { loops: true }; - input: { - for (;;) - if (foo()) break; - } - expect: { - for (; !foo();); - } -} - -drop_if_break_2: { - options = { loops: true }; - input: { - for (;bar();) - if (foo()) break; - } - expect: { - for (; bar() && !foo();); - } -} - -drop_if_break_3: { - options = { loops: true }; - input: { - for (;bar();) { - if (foo()) break; - stuff1(); - stuff2(); - } - } - expect: { - for (; bar() && !foo();) { - stuff1(); - stuff2(); - } - } -} - -drop_if_break_4: { - options = { loops: true, sequences: true }; - input: { - for (;bar();) { - x(); - y(); - if (foo()) break; - z(); - k(); - } - } - expect: { - for (; bar() && (x(), y(), !foo());) z(), k(); - } -} - -drop_if_else_break_1: { - options = { loops: true }; - input: { - for (;;) if (foo()) bar(); else break; - } - expect: { - for (; foo(); ) bar(); - } -} - -drop_if_else_break_2: { - options = { loops: true }; - input: { - for (;bar();) { - if (foo()) baz(); - else break; - } - } - expect: { - for (; bar() && foo();) baz(); - } -} - -drop_if_else_break_3: { - options = { loops: true }; - input: { - for (;bar();) { - if (foo()) baz(); - else break; - stuff1(); - stuff2(); - } - } - expect: { - for (; bar() && foo();) { - baz(); - stuff1(); - stuff2(); - } - } -} - -drop_if_else_break_4: { - options = { loops: true, sequences: true }; - input: { - for (;bar();) { - x(); - y(); - if (foo()) baz(); - else break; - z(); - k(); - } - } - expect: { - for (; bar() && (x(), y(), foo());) baz(), z(), k(); - } -} diff --git a/node_modules/handlebars/node_modules/uglify-js/test/compress/properties.js b/node_modules/handlebars/node_modules/uglify-js/test/compress/properties.js deleted file mode 100644 index 8504596..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/test/compress/properties.js +++ /dev/null @@ -1,54 +0,0 @@ -keep_properties: { - options = { - properties: false - }; - input: { - a["foo"] = "bar"; - } - expect: { - a["foo"] = "bar"; - } -} - -dot_properties: { - options = { - properties: true - }; - input: { - a["foo"] = "bar"; - a["if"] = "if"; - a["*"] = "asterisk"; - a["\u0EB3"] = "unicode"; - a[""] = "whitespace"; - a["1_1"] = "foo"; - } - expect: { - a.foo = "bar"; - a["if"] = "if"; - a["*"] = "asterisk"; - a.\u0EB3 = "unicode"; - a[""] = "whitespace"; - a["1_1"] = "foo"; - } -} - -dot_properties_es5: { - options = { - properties: true, - screw_ie8: true - }; - input: { - a["foo"] = "bar"; - a["if"] = "if"; - a["*"] = "asterisk"; - a["\u0EB3"] = "unicode"; - a[""] = "whitespace"; - } - expect: { - a.foo = "bar"; - a.if = "if"; - a["*"] = "asterisk"; - a.\u0EB3 = "unicode"; - a[""] = "whitespace"; - } -} diff --git a/node_modules/handlebars/node_modules/uglify-js/test/compress/sequences.js b/node_modules/handlebars/node_modules/uglify-js/test/compress/sequences.js deleted file mode 100644 index 6f63ace..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/test/compress/sequences.js +++ /dev/null @@ -1,161 +0,0 @@ -make_sequences_1: { - options = { - sequences: true - }; - input: { - foo(); - bar(); - baz(); - } - expect: { - foo(),bar(),baz(); - } -} - -make_sequences_2: { - options = { - sequences: true - }; - input: { - if (boo) { - foo(); - bar(); - baz(); - } else { - x(); - y(); - z(); - } - } - expect: { - if (boo) foo(),bar(),baz(); - else x(),y(),z(); - } -} - -make_sequences_3: { - options = { - sequences: true - }; - input: { - function f() { - foo(); - bar(); - return baz(); - } - function g() { - foo(); - bar(); - throw new Error(); - } - } - expect: { - function f() { - return foo(), bar(), baz(); - } - function g() { - throw foo(), bar(), new Error(); - } - } -} - -make_sequences_4: { - options = { - sequences: true - }; - input: { - x = 5; - if (y) z(); - - x = 5; - for (i = 0; i < 5; i++) console.log(i); - - x = 5; - for (; i < 5; i++) console.log(i); - - x = 5; - switch (y) {} - - x = 5; - with (obj) {} - } - expect: { - if (x = 5, y) z(); - for (x = 5, i = 0; i < 5; i++) console.log(i); - for (x = 5; i < 5; i++) console.log(i); - switch (x = 5, y) {} - with (x = 5, obj); - } -} - -lift_sequences_1: { - options = { sequences: true }; - input: { - foo = !(x(), y(), bar()); - } - expect: { - x(), y(), foo = !bar(); - } -} - -lift_sequences_2: { - options = { sequences: true, evaluate: true }; - input: { - q = 1 + (foo(), bar(), 5) + 7 * (5 / (3 - (a(), (QW=ER), c(), 2))) - (x(), y(), 5); - } - expect: { - foo(), bar(), a(), QW = ER, c(), x(), y(), q = 36 - } -} - -lift_sequences_3: { - options = { sequences: true, conditionals: true }; - input: { - x = (foo(), bar(), baz()) ? 10 : 20; - } - expect: { - foo(), bar(), x = baz() ? 10 : 20; - } -} - -lift_sequences_4: { - options = { side_effects: true }; - input: { - x = (foo, bar, baz); - } - expect: { - x = baz; - } -} - -for_sequences: { - options = { sequences: true }; - input: { - // 1 - foo(); - bar(); - for (; false;); - // 2 - foo(); - bar(); - for (x = 5; false;); - // 3 - x = (foo in bar); - for (; false;); - // 4 - x = (foo in bar); - for (y = 5; false;); - } - expect: { - // 1 - for (foo(), bar(); false;); - // 2 - for (foo(), bar(), x = 5; false;); - // 3 - x = (foo in bar); - for (; false;); - // 4 - x = (foo in bar); - for (y = 5; false;); - } -} diff --git a/node_modules/handlebars/node_modules/uglify-js/test/compress/switch.js b/node_modules/handlebars/node_modules/uglify-js/test/compress/switch.js deleted file mode 100644 index 62e39cf..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/test/compress/switch.js +++ /dev/null @@ -1,260 +0,0 @@ -constant_switch_1: { - options = { dead_code: true, evaluate: true }; - input: { - switch (1+1) { - case 1: foo(); break; - case 1+1: bar(); break; - case 1+1+1: baz(); break; - } - } - expect: { - bar(); - } -} - -constant_switch_2: { - options = { dead_code: true, evaluate: true }; - input: { - switch (1) { - case 1: foo(); - case 1+1: bar(); break; - case 1+1+1: baz(); - } - } - expect: { - foo(); - bar(); - } -} - -constant_switch_3: { - options = { dead_code: true, evaluate: true }; - input: { - switch (10) { - case 1: foo(); - case 1+1: bar(); break; - case 1+1+1: baz(); - default: - def(); - } - } - expect: { - def(); - } -} - -constant_switch_4: { - options = { dead_code: true, evaluate: true }; - input: { - switch (2) { - case 1: - x(); - if (foo) break; - y(); - break; - case 1+1: - bar(); - default: - def(); - } - } - expect: { - bar(); - def(); - } -} - -constant_switch_5: { - options = { dead_code: true, evaluate: true }; - input: { - switch (1) { - case 1: - x(); - if (foo) break; - y(); - break; - case 1+1: - bar(); - default: - def(); - } - } - expect: { - // the break inside the if ruins our job - // we can still get rid of irrelevant cases. - switch (1) { - case 1: - x(); - if (foo) break; - y(); - } - // XXX: we could optimize this better by inventing an outer - // labeled block, but that's kinda tricky. - } -} - -constant_switch_6: { - options = { dead_code: true, evaluate: true }; - input: { - OUT: { - foo(); - switch (1) { - case 1: - x(); - if (foo) break OUT; - y(); - case 1+1: - bar(); - break; - default: - def(); - } - } - } - expect: { - OUT: { - foo(); - x(); - if (foo) break OUT; - y(); - bar(); - } - } -} - -constant_switch_7: { - options = { dead_code: true, evaluate: true }; - input: { - OUT: { - foo(); - switch (1) { - case 1: - x(); - if (foo) break OUT; - for (var x = 0; x < 10; x++) { - if (x > 5) break; // this break refers to the for, not to the switch; thus it - // shouldn't ruin our optimization - console.log(x); - } - y(); - case 1+1: - bar(); - break; - default: - def(); - } - } - } - expect: { - OUT: { - foo(); - x(); - if (foo) break OUT; - for (var x = 0; x < 10; x++) { - if (x > 5) break; - console.log(x); - } - y(); - bar(); - } - } -} - -constant_switch_8: { - options = { dead_code: true, evaluate: true }; - input: { - OUT: switch (1) { - case 1: - x(); - for (;;) break OUT; - y(); - break; - case 1+1: - bar(); - default: - def(); - } - } - expect: { - OUT: { - x(); - for (;;) break OUT; - y(); - } - } -} - -constant_switch_9: { - options = { dead_code: true, evaluate: true }; - input: { - OUT: switch (1) { - case 1: - x(); - for (;;) if (foo) break OUT; - y(); - case 1+1: - bar(); - default: - def(); - } - } - expect: { - OUT: { - x(); - for (;;) if (foo) break OUT; - y(); - bar(); - def(); - } - } -} - -drop_default_1: { - options = { dead_code: true }; - input: { - switch (foo) { - case 'bar': baz(); - default: - } - } - expect: { - switch (foo) { - case 'bar': baz(); - } - } -} - -drop_default_2: { - options = { dead_code: true }; - input: { - switch (foo) { - case 'bar': baz(); break; - default: - break; - } - } - expect: { - switch (foo) { - case 'bar': baz(); - } - } -} - -keep_default: { - options = { dead_code: true }; - input: { - switch (foo) { - case 'bar': baz(); - default: - something(); - break; - } - } - expect: { - switch (foo) { - case 'bar': baz(); - default: - something(); - } - } -} diff --git a/node_modules/handlebars/node_modules/uglify-js/test/compress/typeof.js b/node_modules/handlebars/node_modules/uglify-js/test/compress/typeof.js deleted file mode 100644 index cefdd43..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/test/compress/typeof.js +++ /dev/null @@ -1,25 +0,0 @@ -typeof_evaluation: { - options = { - evaluate: true - }; - input: { - a = typeof 1; - b = typeof 'test'; - c = typeof []; - d = typeof {}; - e = typeof /./; - f = typeof false; - g = typeof function(){}; - h = typeof undefined; - } - expect: { - a='number'; - b='string'; - c=typeof[]; - d=typeof{}; - e=typeof/./; - f='boolean'; - g='function'; - h='undefined'; - } -} diff --git a/node_modules/handlebars/node_modules/uglify-js/test/run-tests.js b/node_modules/handlebars/node_modules/uglify-js/test/run-tests.js deleted file mode 100755 index 0568c6a..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/test/run-tests.js +++ /dev/null @@ -1,170 +0,0 @@ -#! /usr/bin/env node - -var U = require("../tools/node"); -var path = require("path"); -var fs = require("fs"); -var assert = require("assert"); -var sys = require("util"); - -var tests_dir = path.dirname(module.filename); - -run_compress_tests(); - -/* -----[ utils ]----- */ - -function tmpl() { - return U.string_template.apply(this, arguments); -} - -function log() { - var txt = tmpl.apply(this, arguments); - sys.puts(txt); -} - -function log_directory(dir) { - log("*** Entering [{dir}]", { dir: dir }); -} - -function log_start_file(file) { - log("--- {file}", { file: file }); -} - -function log_test(name) { - log(" Running test [{name}]", { name: name }); -} - -function find_test_files(dir) { - var files = fs.readdirSync(dir).filter(function(name){ - return /\.js$/i.test(name); - }); - if (process.argv.length > 2) { - var x = process.argv.slice(2); - files = files.filter(function(f){ - return x.indexOf(f) >= 0; - }); - } - return files; -} - -function test_directory(dir) { - return path.resolve(tests_dir, dir); -} - -function as_toplevel(input) { - if (input instanceof U.AST_BlockStatement) input = input.body; - else if (input instanceof U.AST_Statement) input = [ input ]; - else throw new Error("Unsupported input syntax"); - var toplevel = new U.AST_Toplevel({ body: input }); - toplevel.figure_out_scope(); - return toplevel; -} - -function run_compress_tests() { - var dir = test_directory("compress"); - log_directory("compress"); - var files = find_test_files(dir); - function test_file(file) { - log_start_file(file); - function test_case(test) { - log_test(test.name); - var options = U.defaults(test.options, { - warnings: false - }); - var cmp = new U.Compressor(options, true); - var expect = make_code(as_toplevel(test.expect), false); - var input = as_toplevel(test.input); - var input_code = make_code(test.input); - var output = input.transform(cmp); - output.figure_out_scope(); - output = make_code(output, false); - if (expect != output) { - log("!!! failed\n---INPUT---\n{input}\n---OUTPUT---\n{output}\n---EXPECTED---\n{expected}\n\n", { - input: input_code, - output: output, - expected: expect - }); - } - } - var tests = parse_test(path.resolve(dir, file)); - for (var i in tests) if (tests.hasOwnProperty(i)) { - test_case(tests[i]); - } - } - files.forEach(function(file){ - test_file(file); - }); -} - -function parse_test(file) { - var script = fs.readFileSync(file, "utf8"); - var ast = U.parse(script, { - filename: file - }); - var tests = {}; - var tw = new U.TreeWalker(function(node, descend){ - if (node instanceof U.AST_LabeledStatement - && tw.parent() instanceof U.AST_Toplevel) { - var name = node.label.name; - tests[name] = get_one_test(name, node.body); - return true; - } - if (!(node instanceof U.AST_Toplevel)) croak(node); - }); - ast.walk(tw); - return tests; - - function croak(node) { - throw new Error(tmpl("Can't understand test file {file} [{line},{col}]\n{code}", { - file: file, - line: node.start.line, - col: node.start.col, - code: make_code(node, false) - })); - } - - function get_one_test(name, block) { - var test = { name: name, options: {} }; - var tw = new U.TreeWalker(function(node, descend){ - if (node instanceof U.AST_Assign) { - if (!(node.left instanceof U.AST_SymbolRef)) { - croak(node); - } - var name = node.left.name; - test[name] = evaluate(node.right); - return true; - } - if (node instanceof U.AST_LabeledStatement) { - assert.ok( - node.label.name == "input" || node.label.name == "expect", - tmpl("Unsupported label {name} [{line},{col}]", { - name: node.label.name, - line: node.label.start.line, - col: node.label.start.col - }) - ); - var stat = node.body; - if (stat instanceof U.AST_BlockStatement) { - if (stat.body.length == 1) stat = stat.body[0]; - else if (stat.body.length == 0) stat = new U.AST_EmptyStatement(); - } - test[node.label.name] = stat; - return true; - } - }); - block.walk(tw); - return test; - }; -} - -function make_code(ast, beautify) { - if (arguments.length == 1) beautify = true; - var stream = U.OutputStream({ beautify: beautify }); - ast.print(stream); - return stream.get(); -} - -function evaluate(code) { - if (code instanceof U.AST_Node) - code = make_code(code); - return new Function("return(" + code + ")")(); -} diff --git a/node_modules/handlebars/node_modules/uglify-js/tools/node.js b/node_modules/handlebars/node_modules/uglify-js/tools/node.js deleted file mode 100644 index c0dd3db..0000000 --- a/node_modules/handlebars/node_modules/uglify-js/tools/node.js +++ /dev/null @@ -1,165 +0,0 @@ -var path = require("path"); -var fs = require("fs"); -var vm = require("vm"); -var sys = require("util"); - -var UglifyJS = vm.createContext({ - sys : sys, - console : console, - MOZ_SourceMap : require("source-map") -}); - -function load_global(file) { - file = path.resolve(path.dirname(module.filename), file); - try { - var code = fs.readFileSync(file, "utf8"); - return vm.runInContext(code, UglifyJS, file); - } catch(ex) { - // XXX: in case of a syntax error, the message is kinda - // useless. (no location information). - sys.debug("ERROR in file: " + file + " / " + ex); - process.exit(1); - } -}; - -var FILES = exports.FILES = [ - "../lib/utils.js", - "../lib/ast.js", - "../lib/parse.js", - "../lib/transform.js", - "../lib/scope.js", - "../lib/output.js", - "../lib/compress.js", - "../lib/sourcemap.js", - "../lib/mozilla-ast.js" -].map(function(file){ - return path.join(path.dirname(fs.realpathSync(__filename)), file); -}); - -FILES.forEach(load_global); - -UglifyJS.AST_Node.warn_function = function(txt) { - sys.error("WARN: " + txt); -}; - -// XXX: perhaps we shouldn't export everything but heck, I'm lazy. -for (var i in UglifyJS) { - if (UglifyJS.hasOwnProperty(i)) { - exports[i] = UglifyJS[i]; - } -} - -exports.minify = function(files, options) { - options = UglifyJS.defaults(options, { - outSourceMap : null, - sourceRoot : null, - inSourceMap : null, - fromString : false, - warnings : false, - mangle : {}, - output : null, - compress : {} - }); - if (typeof files == "string") - files = [ files ]; - - // 1. parse - var toplevel = null; - files.forEach(function(file){ - var code = options.fromString - ? file - : fs.readFileSync(file, "utf8"); - toplevel = UglifyJS.parse(code, { - filename: options.fromString ? "?" : file, - toplevel: toplevel - }); - }); - - // 2. compress - if (options.compress) { - var compress = { warnings: options.warnings }; - UglifyJS.merge(compress, options.compress); - toplevel.figure_out_scope(); - var sq = UglifyJS.Compressor(compress); - toplevel = toplevel.transform(sq); - } - - // 3. mangle - if (options.mangle) { - toplevel.figure_out_scope(); - toplevel.compute_char_frequency(); - toplevel.mangle_names(options.mangle); - } - - // 4. output - var inMap = options.inSourceMap; - var output = {}; - if (typeof options.inSourceMap == "string") { - inMap = fs.readFileSync(options.inSourceMap, "utf8"); - } - if (options.outSourceMap) { - output.source_map = UglifyJS.SourceMap({ - file: options.outSourceMap, - orig: inMap, - root: options.sourceRoot - }); - } - if (options.output) { - UglifyJS.merge(output, options.output); - } - var stream = UglifyJS.OutputStream(output); - toplevel.print(stream); - return { - code : stream + "", - map : output.source_map + "" - }; -}; - -// exports.describe_ast = function() { -// function doitem(ctor) { -// var sub = {}; -// ctor.SUBCLASSES.forEach(function(ctor){ -// sub[ctor.TYPE] = doitem(ctor); -// }); -// var ret = {}; -// if (ctor.SELF_PROPS.length > 0) ret.props = ctor.SELF_PROPS; -// if (ctor.SUBCLASSES.length > 0) ret.sub = sub; -// return ret; -// } -// return doitem(UglifyJS.AST_Node).sub; -// } - -exports.describe_ast = function() { - var out = UglifyJS.OutputStream({ beautify: true }); - function doitem(ctor) { - out.print("AST_" + ctor.TYPE); - var props = ctor.SELF_PROPS.filter(function(prop){ - return !/^\$/.test(prop); - }); - if (props.length > 0) { - out.space(); - out.with_parens(function(){ - props.forEach(function(prop, i){ - if (i) out.space(); - out.print(prop); - }); - }); - } - if (ctor.documentation) { - out.space(); - out.print_string(ctor.documentation); - } - if (ctor.SUBCLASSES.length > 0) { - out.space(); - out.with_block(function(){ - ctor.SUBCLASSES.forEach(function(ctor, i){ - out.indent(); - doitem(ctor); - out.newline(); - }); - }); - } - }; - doitem(UglifyJS.AST_Node); - return out + ""; -}; diff --git a/node_modules/handlebars/package.json b/node_modules/handlebars/package.json deleted file mode 100644 index 1e86a2d..0000000 --- a/node_modules/handlebars/package.json +++ /dev/null @@ -1,102 +0,0 @@ -{ - "name": "handlebars", - "barename": "handlebars", - "version": "3.0.3", - "description": "Handlebars provides the power necessary to let you build semantic templates effectively with no frustration", - "homepage": "http://www.handlebarsjs.com/", - "keywords": [ - "handlebars", - "mustache", - "template", - "html" - ], - "repository": { - "type": "git", - "url": "git+https://github.com/wycats/handlebars.js.git" - }, - "author": { - "name": "Yehuda Katz" - }, - "license": "MIT", - "engines": { - "node": ">=0.4.7" - }, - "dependencies": { - "optimist": "^0.6.1", - "source-map": "^0.1.40", - "uglify-js": "~2.3" - }, - "optionalDependencies": { - "uglify-js": "~2.3" - }, - "devDependencies": { - "async": "^0.9.0", - "aws-sdk": "~1.5.0", - "babel-loader": "^5.0.0", - "babel-runtime": "^5.1.10", - "benchmark": "~1.0", - "dustjs-linkedin": "^2.0.2", - "eco": "~1.1.0-rc-3", - "grunt": "~0.4.1", - "grunt-babel": "^5.0.0", - "grunt-cli": "~0.1.10", - "grunt-contrib-clean": "0.x", - "grunt-contrib-concat": "0.x", - "grunt-contrib-connect": "0.x", - "grunt-contrib-copy": "0.x", - "grunt-contrib-requirejs": "0.x", - "grunt-contrib-uglify": "0.x", - "grunt-contrib-watch": "0.x", - "grunt-eslint": "^11.0.0", - "grunt-saucelabs": "8.x", - "grunt-webpack": "^1.0.8", - "istanbul": "^0.3.0", - "jison": "~0.3.0", - "keen.io": "0.0.3", - "mocha": "~1.20.0", - "mustache": "0.x", - "semver": "^4.0.0", - "underscore": "^1.5.1" - }, - "main": "lib/index.js", - "bin": { - "handlebars": "bin/handlebars" - }, - "scripts": { - "test": "grunt" - }, - "jspm": { - "main": "handlebars", - "directories": { - "lib": "dist/amd" - }, - "buildConfig": { - "minify": true - } - }, - "gitHead": "891f48b7e9c321dd9cbe7a898533eb6b2434b8a0", - "bugs": { - "url": "https://github.com/wycats/handlebars.js/issues" - }, - "_id": "handlebars@3.0.3", - "_shasum": "0e09651a2f0fb3c949160583710d551f92e6d2ad", - "_from": "handlebars@>=3.0.0 <3.1.0", - "_npmVersion": "1.4.28", - "_npmUser": { - "name": "kpdecker", - "email": "kpdecker@gmail.com" - }, - "maintainers": [ - { - "name": "kpdecker", - "email": "kpdecker@gmail.com" - } - ], - "dist": { - "shasum": "0e09651a2f0fb3c949160583710d551f92e6d2ad", - "tarball": "http://registry.npmjs.org/handlebars/-/handlebars-3.0.3.tgz" - }, - "directories": {}, - "_resolved": "https://registry.npmjs.org/handlebars/-/handlebars-3.0.3.tgz", - "readme": "ERROR: No README data found!" -} diff --git a/node_modules/handlebars/release-notes.md b/node_modules/handlebars/release-notes.md deleted file mode 100644 index 21a5346..0000000 --- a/node_modules/handlebars/release-notes.md +++ /dev/null @@ -1,378 +0,0 @@ -# Release Notes - -## Development - -[Commits](https://github.com/wycats/handlebars.js/compare/v3.0.3...master) - -## v3.0.3 - April 28th, 2015 -- [#1004](https://github.com/wycats/handlebars.js/issues/1004) - Latest version breaks with RequireJS (global is undefined) ([@boskee](https://api.github.com/users/boskee)) - -[Commits](https://github.com/wycats/handlebars.js/compare/v3.0.2...v3.0.3) - -## v3.0.2 - April 20th, 2015 -- [#998](https://github.com/wycats/handlebars.js/pull/998) - Add full support for es6 ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#994](https://github.com/wycats/handlebars.js/issues/994) - Access Handlebars.Visitor in browser ([@tamlyn](https://api.github.com/users/tamlyn)) -- [#990](https://github.com/wycats/handlebars.js/issues/990) - Allow passing null/undefined literals subexpressions ([@blimmer](https://api.github.com/users/blimmer)) -- [#989](https://github.com/wycats/handlebars.js/issues/989) - Source-map error with requirejs ([@SteppeEagle](https://api.github.com/users/SteppeEagle)) -- [#967](https://github.com/wycats/handlebars.js/issues/967) - can't access "this" property ([@75lb](https://api.github.com/users/75lb)) -- Use captureStackTrace for error handler - a009a97 -- Ignore branches tested without coverage monitoring - 37a664b - -[Commits](https://github.com/wycats/handlebars.js/compare/v3.0.1...v3.0.2) - -## v3.0.1 - March 24th, 2015 -- [#984](https://github.com/wycats/handlebars.js/pull/984) - Adding documentation for passing arguments into partials ([@johneke](https://api.github.com/users/johneke)) -- [#973](https://github.com/wycats/handlebars.js/issues/973) - version 3 is slower than version 2 ([@elover](https://api.github.com/users/elover)) -- [#966](https://github.com/wycats/handlebars.js/issues/966) - "handlebars --version" does not work with v3.0.0 ([@abloomston](https://api.github.com/users/abloomston)) -- [#964](https://github.com/wycats/handlebars.js/pull/964) - default is a reserved word ([@grassick](https://api.github.com/users/grassick)) -- [#962](https://github.com/wycats/handlebars.js/pull/962) - Add dashbars' link on README. ([@pismute](https://api.github.com/users/pismute)) - -[Commits](https://github.com/wycats/handlebars.js/compare/v3.0.0...v3.0.1) - -## v3.0.0 - February 10th, 2015 -- [#941](https://github.com/wycats/handlebars.js/pull/941) - Add support for dynamic partial names ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#940](https://github.com/wycats/handlebars.js/pull/940) - Add missing reserved words so compiler knows to use array syntax: ([@mattflaschen](https://api.github.com/users/mattflaschen)) -- [#938](https://github.com/wycats/handlebars.js/pull/938) - Fix example using #with helper ([@diwo](https://api.github.com/users/diwo)) -- [#930](https://github.com/wycats/handlebars.js/pull/930) - Add parent tracking and mutation to AST visitors ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#926](https://github.com/wycats/handlebars.js/issues/926) - Depthed lookups fail when program duplicator runs ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#918](https://github.com/wycats/handlebars.js/pull/918) - Add instructions for 'spec/mustache' to CONTRIBUTING.md, fix a few typos ([@oneeman](https://api.github.com/users/oneeman)) -- [#915](https://github.com/wycats/handlebars.js/pull/915) - Ast update ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#910](https://github.com/wycats/handlebars.js/issues/910) - Different behavior of {{@last}} when {{#each}} in {{#each}} ([@zordius](https://api.github.com/users/zordius)) -- [#907](https://github.com/wycats/handlebars.js/issues/907) - Implement named helper variable references ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#906](https://github.com/wycats/handlebars.js/pull/906) - Add parser support for block params ([@mmun](https://api.github.com/users/mmun)) -- [#903](https://github.com/wycats/handlebars.js/issues/903) - Only provide aliases for multiple use calls ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#902](https://github.com/wycats/handlebars.js/pull/902) - Generate Source Maps ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#901](https://github.com/wycats/handlebars.js/issues/901) - Still escapes with noEscape enabled on isolated Handlebars environment ([@zedknight](https://api.github.com/users/zedknight)) -- [#896](https://github.com/wycats/handlebars.js/pull/896) - Simplify BlockNode by removing intermediate MustacheNode ([@mmun](https://api.github.com/users/mmun)) -- [#892](https://github.com/wycats/handlebars.js/pull/892) - Implement parser for else chaining of helpers ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#889](https://github.com/wycats/handlebars.js/issues/889) - Consider extensible parser API ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#887](https://github.com/wycats/handlebars.js/issues/887) - Handlebars.noConflict() option? ([@bradvogel](https://api.github.com/users/bradvogel)) -- [#886](https://github.com/wycats/handlebars.js/issues/886) - Add SafeString to context (or use duck-typing) ([@dominicbarnes](https://api.github.com/users/dominicbarnes)) -- [#870](https://github.com/wycats/handlebars.js/pull/870) - Registering undefined partial throws exception. ([@max-b](https://api.github.com/users/max-b)) -- [#866](https://github.com/wycats/handlebars.js/issues/866) - comments don't respect whitespace control ([@75lb](https://api.github.com/users/75lb)) -- [#863](https://github.com/wycats/handlebars.js/pull/863) - + jsDelivr CDN info ([@tomByrer](https://api.github.com/users/tomByrer)) -- [#858](https://github.com/wycats/handlebars.js/issues/858) - Disable new default auto-indent at included partials ([@majodev](https://api.github.com/users/majodev)) -- [#856](https://github.com/wycats/handlebars.js/pull/856) - jspm compatibility ([@MajorBreakfast](https://api.github.com/users/MajorBreakfast)) -- [#805](https://github.com/wycats/handlebars.js/issues/805) - Request: "strict" lookups ([@nzakas](https://api.github.com/users/nzakas)) - -- Export the default object for handlebars/runtime - 5594416 -- Lookup partials when undefined - 617dd57 - -Compatibility notes: -- Runtime breaking changes. Must match 3.x runtime and precompiler. -- The AST has been upgraded to a public API. - - There are a number of changes to this, but the format is now documented in docs/compiler-api.md - - The Visitor API has been expanded to support mutation and provide a base implementation -- The `JavaScriptCompiler` APIs have been formalized and documented. As part of the sourcemap handling these should be updated to return arrays for concatenation. -- `JavaScriptCompiler.namespace` has been removed as it was unused. -- `SafeString` is now duck typed on `toHTML` - -New Features: -- noConflict -- Source Maps -- Block Params -- Strict Mode -- @last and other each changes -- Chained else blocks -- @data methods can now have helper parameters passed to them -- Dynamic partials - -[Commits](https://github.com/wycats/handlebars.js/compare/v2.0.0...v3.0.0) - -## v2.0.0 - September 1st, 2014 -- Update jsfiddle to 2.0.0-beta.1 - 0670f65 -- Add contrib note regarding handlebarsjs.com docs - 4d17e3c -- Play nice with gemspec version numbers - 64d5481 - -[Commits](https://github.com/wycats/handlebars.js/compare/v2.0.0-beta.1...v2.0.0) - -## v2.0.0-beta.1 - August 26th, 2014 -- [#787](https://github.com/wycats/handlebars.js/pull/787) - Remove whitespace surrounding standalone statements ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#827](https://github.com/wycats/handlebars.js/issues/827) - Render false literal as “false” ([@scoot557](https://api.github.com/users/scoot557)) -- [#767](https://github.com/wycats/handlebars.js/issues/767) - Subexpressions bug with hash and context ([@evensoul](https://api.github.com/users/evensoul)) -- Changes to 0/undefined handling - - [#731](https://github.com/wycats/handlebars.js/pull/731) - Strange behavior for {{#foo}} {{bar}} {{/foo}} when foo is 0 ([@kpdecker](https://api.github.com/users/kpdecker)) - - [#820](https://github.com/wycats/handlebars.js/issues/820) - strange behavior for {{foo.bar}} when foo is 0 or null or false ([@zordius](https://api.github.com/users/zordius)) - - [#837](https://github.com/wycats/handlebars.js/issues/837) - Strange input for custom helper ( foo.bar == false when foo is undefined ) ([@zordius](https://api.github.com/users/zordius)) -- [#819](https://github.com/wycats/handlebars.js/pull/819) - Implement recursive field lookup ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#764](https://github.com/wycats/handlebars.js/issues/764) - This reference not working for helpers ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#773](https://github.com/wycats/handlebars.js/issues/773) - Implicit parameters in {{#each}} introduces a peculiarity in helpers calling convention ([@Bertrand](https://api.github.com/users/Bertrand)) -- [#783](https://github.com/wycats/handlebars.js/issues/783) - helperMissing and consistency for different expression types ([@ErisDS](https://api.github.com/users/ErisDS)) -- [#795](https://github.com/wycats/handlebars.js/pull/795) - Turn the precompile script into a wrapper around a module. ([@jwietelmann](https://api.github.com/users/jwietelmann)) -- [#823](https://github.com/wycats/handlebars.js/pull/823) - Support inverse sections on the with helper ([@dan-manges](https://api.github.com/users/dan-manges)) -- [#834](https://github.com/wycats/handlebars.js/pull/834) - Refactor blocks, programs and inverses ([@mmun](https://api.github.com/users/mmun)) -- [#852](https://github.com/wycats/handlebars.js/issues/852) - {{foo~}} space control behavior is different from older version ([@zordius](https://api.github.com/users/zordius)) -- [#835](https://github.com/wycats/handlebars.js/issues/835) - Templates overwritten if file is loaded twice - -- Expose escapeExpression on the root object - 980c38c -- Remove nested function eval in blockHelperMissing - 6f22ec1 -- Fix compiler program de-duping - 9e3f824 - -Compatibility notes: -- The default build now outputs a generic UMD wrapper. This should be transparent change but may cause issues in some environments. -- Runtime compatibility breaks in both directions. Ensure that both compiler and client are upgraded to 2.0.0-beta.1 or higher at the same time. - - `programWithDepth` has been removed an instead an array of context values is passed to fields needing depth lookups. -- `false` values are now printed to output rather than silently dropped -- Lines containing only block statements and whitespace are now removed. This matches the Mustache spec but may cause issues with code that expects whitespace to exist but would not otherwise. -- Partials that are standalone will now indent their rendered content -- `AST.ProgramNode`'s signature has changed. -- Numerious methods/features removed from psuedo-API classes - - `JavaScriptCompiler.register` - - `JavaScriptCompiler.replaceStack` no longer supports non-inline replace - - `Compiler.disassemble` - - `DECLARE` opcode - - `strip` opcode - - `lookup` opcode - - Content nodes may have their `string` values mutated over time. `original` field provides the unmodified value. -- Removed unused `Handlebars.registerHelper` `inverse` parameter -- `each` helper requires iterator parameter - -[Commits](https://github.com/wycats/handlebars.js/compare/v2.0.0-alpha.4...v2.0.0-beta.1) - -## v2.0.0-alpha.4 - May 19th, 2014 -- Expose setup wrappers for compiled templates - 3638874 - -[Commits](https://github.com/wycats/handlebars.js/compare/v2.0.0-alpha.3...v2.0.0-alpha.4) - -## v2.0.0-alpha.3 - May 19th, 2014 -- [#797](https://github.com/wycats/handlebars.js/pull/797) - Pass full helper ID to helperMissing when options are provided ([@tomdale](https://api.github.com/users/tomdale)) -- [#793](https://github.com/wycats/handlebars.js/pull/793) - Ensure isHelper is coerced to a boolean ([@mmun](https://api.github.com/users/mmun)) -- Refactor template init logic - 085e5e1 - -[Commits](https://github.com/wycats/handlebars.js/compare/v2.0.0-alpha.2...v2.0.0-alpha.3) - -## v2.0.0-alpha.2 - March 6th, 2014 -- [#756](https://github.com/wycats/handlebars.js/pull/756) - fix bug in IE<=8 (no Array::map), closes #751 ([@jenseng](https://api.github.com/users/jenseng)) -- [#749](https://github.com/wycats/handlebars.js/pull/749) - properly handle multiple subexpressions in the same hash, fixes #748 ([@jenseng](https://api.github.com/users/jenseng)) -- [#743](https://github.com/wycats/handlebars.js/issues/743) - subexpression confusion/problem? ([@waynedpj](https://api.github.com/users/waynedpj)) -- [#746](https://github.com/wycats/handlebars.js/issues/746) - [CLI] support `handlebars --version` ([@apfelbox](https://api.github.com/users/apfelbox)) -- [#747](https://github.com/wycats/handlebars.js/pull/747) - updated grunt-saucelabs, failing tests revealed ([@Jonahss](https://api.github.com/users/Jonahss)) -- Make JSON a requirement for the compiler. - 058c0fb -- Temporarily kill the AWS publish CI step - 8347ee2 - -Compatibility notes: -- A JSON polyfill is required to run the compiler under IE8 and below. It's recommended that the precompiler be used in lieu of running the compiler on these legacy environments. - -[Commits](https://github.com/wycats/handlebars.js/compare/v2.0.0-alpha.1...v2.0.0-alpha.2) - -## v2.0.0-alpha.1 - February 10th, 2014 -- [#182](https://github.com/wycats/handlebars.js/pull/182) - Allow passing hash parameters to partials ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#392](https://github.com/wycats/handlebars.js/pull/392) - Access to root context in partials and helpers ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#472](https://github.com/wycats/handlebars.js/issues/472) - Helpers cannot have decimal parameters ([@kayleg](https://api.github.com/users/kayleg)) -- [#569](https://github.com/wycats/handlebars.js/pull/569) - Unable to lookup array values using @index ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#491](https://github.com/wycats/handlebars.js/pull/491) - For nested helpers: get the @ variables of the outer helper from the inner one ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#669](https://github.com/wycats/handlebars.js/issues/669) - Ability to unregister a helper ([@dbachrach](https://api.github.com/users/dbachrach)) -- [#730](https://github.com/wycats/handlebars.js/pull/730) - Raw block helpers ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#634](https://github.com/wycats/handlebars.js/pull/634) - It would be great to have the helper name passed to `blockHelperMissing` ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#729](https://github.com/wycats/handlebars.js/pull/729) - Convert template spec to object literal ([@kpdecker](https://api.github.com/users/kpdecker)) - -- [#658](https://github.com/wycats/handlebars.js/issues/658) - Depthed helpers do not work after an upgrade from 1.0.0 ([@xibxor](https://api.github.com/users/xibxor)) -- [#671](https://github.com/wycats/handlebars.js/issues/671) - Crashes on no-parameter {{#each}} ([@stepancheg](https://api.github.com/users/stepancheg)) -- [#689](https://github.com/wycats/handlebars.js/issues/689) - broken template precompilation ([@AAS](https://api.github.com/users/AAS)) -- [#698](https://github.com/wycats/handlebars.js/pull/698) - Fix parser generation under windows ([@osiris43](https://api.github.com/users/osiris43)) -- [#699](https://github.com/wycats/handlebars.js/issues/699) - @DATA not compiles to invalid JS in stringParams mode ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#705](https://github.com/wycats/handlebars.js/issues/705) - 1.3.0 can not be wrapped in an IIFE ([@craigteegarden](https://api.github.com/users/craigteegarden)) -- [#706](https://github.com/wycats/handlebars.js/pull/706) - README: Use with helper instead of relying on blockHelperMissing ([@scottgonzalez](https://api.github.com/users/scottgonzalez)) - -- [#700](https://github.com/wycats/handlebars.js/pull/700) - Remove redundant conditions ([@blakeembrey](https://api.github.com/users/blakeembrey)) -- [#704](https://github.com/wycats/handlebars.js/pull/704) - JavaScript Compiler Cleanup ([@blakeembrey](https://api.github.com/users/blakeembrey)) - -Compatibility notes: -- `helperMissing` helper no longer has the indexed name argument. Helper name is now available via `options.name`. -- Precompiler output has changed, which breaks compatibility with prior versions of the runtime and precompiled output. -- `JavaScriptCompiler.compilerInfo` now returns generic objects rather than javascript source. -- AST changes - - INTEGER -> NUMBER - - Additional PartialNode hash parameter - - New RawBlockNode type -- Data frames now have a `_parent` field. This is internal but is enumerable for performance/compatability reasons. - -[Commits](https://github.com/wycats/handlebars.js/compare/v1.3.0...v2.0.0-alpha.1) - -## v1.3.0 - January 1st, 2014 -- [#690](https://github.com/wycats/handlebars.js/pull/690) - Added support for subexpressions ([@machty](https://api.github.com/users/machty)) -- [#696](https://github.com/wycats/handlebars.js/pull/696) - Fix for reserved keyword "default" ([@nateirwin](https://api.github.com/users/nateirwin)) -- [#692](https://github.com/wycats/handlebars.js/pull/692) - add line numbers to nodes when parsing ([@fivetanley](https://api.github.com/users/fivetanley)) -- [#695](https://github.com/wycats/handlebars.js/pull/695) - Pull options out from param setup to allow easier extension ([@blakeembrey](https://api.github.com/users/blakeembrey)) -- [#694](https://github.com/wycats/handlebars.js/pull/694) - Make the environment reusable ([@blakeembrey](https://api.github.com/users/blakeembrey)) -- [#636](https://github.com/wycats/handlebars.js/issues/636) - Print line and column of errors ([@sgronblo](https://api.github.com/users/sgronblo)) -- Use literal for data lookup - c1a93d3 -- Add stack handling sanity checks - cd885bf -- Fix stack id "leak" on replaceStack - ddfe457 -- Fix incorrect stack pop when replacing literals - f4d337d - -[Commits](https://github.com/wycats/handlebars.js/compare/v1.2.1...v1.3.0) - -## v1.2.1 - December 26th, 2013 -- [#684](https://github.com/wycats/handlebars.js/pull/684) - Allow any number of trailing characters for valid JavaScript variable ([@blakeembrey](https://api.github.com/users/blakeembrey)) -- [#686](https://github.com/wycats/handlebars.js/pull/686) - Falsy AMD module names in version 1.2.0 ([@kpdecker](https://api.github.com/users/kpdecker)) - -[Commits](https://github.com/wycats/handlebars.js/compare/v1.2.0...v1.2.1) - -## v1.2.0 - December 23rd, 2013 -- [#675](https://github.com/wycats/handlebars.js/issues/675) - Cannot compile empty template for partial ([@erwinw](https://api.github.com/users/erwinw)) -- [#677](https://github.com/wycats/handlebars.js/issues/677) - Triple brace statements fail under IE ([@hamzaCM](https://api.github.com/users/hamzaCM)) -- [#655](https://github.com/wycats/handlebars.js/issues/655) - Loading Handlebars using bower ([@niki4810](https://api.github.com/users/niki4810)) -- [#657](https://github.com/wycats/handlebars.js/pull/657) - Fixes issue where cli compiles non handlebars templates ([@chrishoage](https://api.github.com/users/chrishoage)) -- [#681](https://github.com/wycats/handlebars.js/pull/681) - Adds in-browser testing and Saucelabs CI ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#661](https://github.com/wycats/handlebars.js/pull/661) - Add @first and @index to #each object iteration ([@cgp](https://api.github.com/users/cgp)) -- [#650](https://github.com/wycats/handlebars.js/pull/650) - Handlebars is MIT-licensed ([@thomasboyt](https://api.github.com/users/thomasboyt)) -- [#641](https://github.com/wycats/handlebars.js/pull/641) - Document ember testing process ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#662](https://github.com/wycats/handlebars.js/issues/662) - handlebars-source 1.1.2 is missing from RubyGems. -- [#656](https://github.com/wycats/handlebars.js/issues/656) - Expose COMPILER_REVISION checks as a hook ([@machty](https://api.github.com/users/machty)) -- [#668](https://github.com/wycats/handlebars.js/issues/668) - Consider publishing handlebars-runtime as a separate module on npm ([@dlmanning](https://api.github.com/users/dlmanning)) -- [#679](https://github.com/wycats/handlebars.js/issues/679) - Unable to override invokePartial ([@mattbrailsford](https://api.github.com/users/mattbrailsford)) -- [#646](https://github.com/wycats/handlebars.js/pull/646) - Fix "\\{{" immediately following "\{{" ([@dmarcotte](https://api.github.com/users/dmarcotte)) -- Allow extend to work with non-prototyped objects - eb53f2e -- Add JavascriptCompiler public API tests - 1a751b2 -- Add AST test coverage for more complex paths - ddea5be -- Fix handling of boolean escape in MustacheNode - b4968bb - -Compatibility notes: -- `@index` and `@first` are now supported for `each` iteration on objects -- `Handlebars.VM.checkRevision` and `Handlebars.JavaScriptCompiler.prototype.compilerInfo` now available to modify the version checking behavior. -- Browserify users may link to the runtime library via `require('handlebars/runtime')` - -[Commits](https://github.com/wycats/handlebars.js/compare/v1.1.2...v1.2.0) - -## v1.1.2 - November 5th, 2013 - -- [#645](https://github.com/wycats/handlebars.js/issues/645) - 1.1.1 fails under IE8 ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#644](https://github.com/wycats/handlebars.js/issues/644) - Using precompiled templates (AMD mode) with handlebars.runtime 1.1.1 ([@fddima](https://api.github.com/users/fddima)) - -- Add simple binary utility tests - 96a45a4 -- Fix empty string compilation - eea708a - -[Commits](https://github.com/wycats/handlebars.js/compare/v1.1.1...v1.1.2) - -## v1.1.1 - November 4th, 2013 - -- [#642](https://github.com/wycats/handlebars.js/issues/642) - handlebars 1.1.0 are broken with nodejs - -- Fix release notes link - 17ba258 - -[Commits](https://github.com/wycats/handlebars.js/compare/v1.1.0...v1.1.1) - -## v1.1.0 - November 3rd, 2013 - -- [#628](https://github.com/wycats/handlebars.js/pull/628) - Convert code to ES6 modules ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#336](https://github.com/wycats/handlebars.js/pull/336) - Add whitespace control syntax ([@kpdecker](https://api.github.com/users/kpdecker)) -- [#535](https://github.com/wycats/handlebars.js/pull/535) - Fix for probable JIT error under Safari ([@sorentwo](https://api.github.com/users/sorentwo)) -- [#483](https://github.com/wycats/handlebars.js/issues/483) - Add first and last @ vars to each helper ([@denniskuczynski](https://api.github.com/users/denniskuczynski)) -- [#557](https://github.com/wycats/handlebars.js/pull/557) - `\\{{foo}}` escaping only works in some situations ([@dmarcotte](https://api.github.com/users/dmarcotte)) -- [#552](https://github.com/wycats/handlebars.js/pull/552) - Added BOM removal flag. ([@blessenm](https://api.github.com/users/blessenm)) -- [#543](https://github.com/wycats/handlebars.js/pull/543) - publish passing master builds to s3 ([@fivetanley](https://api.github.com/users/fivetanley)) - -- [#608](https://github.com/wycats/handlebars.js/issues/608) - Add `includeZero` flag to `if` conditional -- [#498](https://github.com/wycats/handlebars.js/issues/498) - `Handlebars.compile` fails on empty string although a single blank works fine -- [#599](https://github.com/wycats/handlebars.js/issues/599) - lambda helpers only receive options if used with arguments -- [#592](https://github.com/wycats/handlebars.js/issues/592) - Optimize array and subprogram performance -- [#571](https://github.com/wycats/handlebars.js/issues/571) - uglify upgrade breaks compatibility with older versions of node -- [#587](https://github.com/wycats/handlebars.js/issues/587) - Partial inside partial breaks? - - -Compatibility notes: -- The project now includes separate artifacts for AMD, CommonJS, and global objects. - - AMD: Users may load the bundled `handlebars.amd.js` or `handlebars.runtime.amd.js` files or load individual modules directly. AMD users should also note that the handlebars object is exposed via the `default` field on the imported object. This [gist](https://gist.github.com/wycats/7417be0dc361a69d5916) provides some discussion of possible compatibility shims. - - CommonJS/Node: Node loading occurs as normal via `require` - - Globals: The `handlebars.js` and `handlebars.runtime.js` files should behave in the same manner as the v1.0.12 / 1.0.0 release. -- Build artifacts have been removed from the repository. [npm][npm], [components/handlebars.js][components], [cdnjs][cdnjs], or the [builds page][builds-page] should now be used as the source of built artifacts. -- Context-stored helpers are now always passed the `options` hash. Previously no-argument helpers did not have this argument. - - -[Commits](https://github.com/wycats/handlebars.js/compare/v1.0.12...v1.1.0) - -## v1.0.12 / 1.0.0 - May 31 2013 - -- [#515](https://github.com/wycats/handlebars.js/issues/515) - Add node require extensions support ([@jjclark1982](https://github.com/jjclark1982)) -- [#517](https://github.com/wycats/handlebars.js/issues/517) - Fix amd precompiler output with directories ([@blessenm](https://github.com/blessenm)) -- [#433](https://github.com/wycats/handlebars.js/issues/433) - Add support for unicode ids -- [#469](https://github.com/wycats/handlebars.js/issues/469) - Add support for `?` in ids -- [#534](https://github.com/wycats/handlebars.js/issues/534) - Protect from object prototype modifications -- [#519](https://github.com/wycats/handlebars.js/issues/519) - Fix partials with . name ([@jamesgorrie](https://github.com/jamesgorrie)) -- [#519](https://github.com/wycats/handlebars.js/issues/519) - Allow ID or strings in partial names -- [#437](https://github.com/wycats/handlebars.js/issues/437) - Require matching brace counts in escaped expressions -- Merge passed partials and helpers with global namespace values -- Add support for complex ids in @data references -- Docs updates - -Compatibility notes: -- The parser is now stricter on `{{{`, requiring that the end token be `}}}`. Templates that do not - follow this convention should add the additional brace value. -- Code that relies on global the namespace being muted when custom helpers or partials are passed will need to explicitly pass an `undefined` value for any helpers that should not be available. -- The compiler version has changed. Precompiled templates with 1.0.12 or higher must use the 1.0.0 or higher runtime. - -[Commits](https://github.com/wycats/handlebars.js/compare/v1.0.11...v1.0.12) - -## v1.0.11 / 1.0.0-rc4 - May 13 2013 - -- [#458](https://github.com/wycats/handlebars.js/issues/458) - Fix `./foo` syntax ([@jpfiset](https://github.com/jpfiset)) -- [#460](https://github.com/wycats/handlebars.js/issues/460) - Allow `:` in unescaped identifers ([@jpfiset](https://github.com/jpfiset)) -- [#471](https://github.com/wycats/handlebars.js/issues/471) - Create release notes (These!) -- [#456](https://github.com/wycats/handlebars.js/issues/456) - Allow escaping of `\\` -- [#211](https://github.com/wycats/handlebars.js/issues/211) - Fix exception in `escapeExpression` -- [#375](https://github.com/wycats/handlebars.js/issues/375) - Escape unicode newlines -- [#461](https://github.com/wycats/handlebars.js/issues/461) - Do not fail when compiling `""` -- [#302](https://github.com/wycats/handlebars.js/issues/302) - Fix sanity check in knownHelpersOnly mode -- [#369](https://github.com/wycats/handlebars.js/issues/369) - Allow registration of multiple helpers and partial by passing definition object -- Add bower package declaration ([@DevinClark](https://github.com/DevinClark)) -- Add NuSpec package declaration ([@MikeMayer](https://github.com/MikeMayer)) -- Handle empty context in `with` ([@thejohnfreeman](https://github.com/thejohnfreeman)) -- Support custom template extensions in CLI ([@matteoagosti](https://github.com/matteoagosti)) -- Fix Rhino support ([@broady](https://github.com/broady)) -- Include contexts in string mode ([@leshill](https://github.com/leshill)) -- Return precompiled scripts when compiling to AMD ([@JamesMaroney](https://github.com/JamesMaroney)) -- Docs updates ([@iangreenleaf](https://github.com/iangreenleaf), [@gilesbowkett](https://github.com/gilesbowkett), [@utkarsh2012](https://github.com/utkarsh2012)) -- Fix `toString` handling under IE and browserify ([@tommydudebreaux](https://github.com/tommydudebreaux)) -- Add program metadata - -[Commits](https://github.com/wycats/handlebars.js/compare/v1.0.10...v1.0.11) - -## v1.0.10 - Node - Feb 27 2013 - -- [#428](https://github.com/wycats/handlebars.js/issues/428) - Fix incorrect rendering of nested programs -- Fix exception message ([@tricknotes](https://github.com/tricknotes)) -- Added negative number literal support -- Concert library to single IIFE -- Add handlebars-source gemspec ([@machty](https://github.com/machty)) - -[Commits](https://github.com/wycats/handlebars.js/compare/v1.0.9...v1.0.10) - -## v1.0.9 - Node - Feb 15 2013 - -- Added `Handlebars.create` API in node module for sandboxed instances ([@tommydudebreaux](https://github.com/tommydudebreaux)) - -[Commits](https://github.com/wycats/handlebars.js/compare/1.0.0-rc.3...v1.0.9) - -## 1.0.0-rc3 - Browser - Feb 14 2013 - -- Prevent use of `this` or `..` in illogical place ([@leshill](https://github.com/leshill)) -- Allow AST passing for `parse`/`compile`/`precompile` ([@machty](https://github.com/machty)) -- Optimize generated output by inlining statements where possible -- Check compiler version when evaluating templates -- Package browser dist in npm package - -[Commits](https://github.com/wycats/handlebars.js/compare/v1.0.8...1.0.0-rc.3) - -## Prior Versions - -When upgrading from the Handlebars 0.9 series, be aware that the -signature for passing custom helpers or partials to templates has -changed. - -Instead of: - -```js -template(context, helpers, partials, [data]) -``` - -Use: - -```js -template(context, {helpers: helpers, partials: partials, data: data}) -``` - -[builds-page]: http://builds.handlebarsjs.com.s3.amazonaws.com/index.html -[cdnjs]: http://cdnjs.com/libraries/handlebars.js/ -[components]: https://github.com/components/handlebars.js -[npm]: https://npmjs.org/package/handlebars diff --git a/node_modules/hapi/.npmignore b/node_modules/hapi/.npmignore deleted file mode 100644 index c67999d..0000000 --- a/node_modules/hapi/.npmignore +++ /dev/null @@ -1,16 +0,0 @@ -.idea -*.iml -npm-debug.log -dump.rdb -node_modules -results.tap -results.xml -config.json -.DS_Store -*/.DS_Store -*/*/.DS_Store -._* -*/._* -*/*/._* -coverage.* -.settings diff --git a/node_modules/hapi/.travis.yml b/node_modules/hapi/.travis.yml deleted file mode 100755 index f502178..0000000 --- a/node_modules/hapi/.travis.yml +++ /dev/null @@ -1,6 +0,0 @@ -language: node_js - -node_js: - - 0.10 - - 0.12 - - iojs diff --git a/node_modules/hapi/CONTRIBUTING.md b/node_modules/hapi/CONTRIBUTING.md deleted file mode 100755 index 529d316..0000000 --- a/node_modules/hapi/CONTRIBUTING.md +++ /dev/null @@ -1,14 +0,0 @@ -# How to contribute -We welcome contributions from the community and are pleased to have them. Please follow this guide when logging issues or making code changes. - -## Logging Issues -All issues should be created using the [new issue form](https://github.com/hapijs/hapi/issues/new). Clearly describe the issue including steps to reproduce if there are any. Also, make sure to indicate the earliest version that has the issue being reported. - -## Patching Code -Code changes are welcome and should follow the guidelines below. - -* Fork the repository on GitHub. -* Fix the issue ensuring that your code follows the [style guide](https://github.com/hapijs/contrib/blob/master/Style.md). -* Add tests for your new code ensuring that you have 100% code coverage (we can help you reach 100% but will not merge without it). - * Run `make test-cov-html` to generate a report of test coverage -* [Pull requests](http://help.github.com/send-pull-requests/) should be made to the [master branch](https://github.com/hapijs/hapi/tree/master). diff --git a/node_modules/hapi/LICENSE b/node_modules/hapi/LICENSE deleted file mode 100755 index 5530904..0000000 --- a/node_modules/hapi/LICENSE +++ /dev/null @@ -1,31 +0,0 @@ -Copyright (c) 2011-2014, Walmart and other contributors. -Copyright (c) 2011, Yahoo Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The names of any contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - * * * - -The complete list of contributors can be found at: https://github.com/hapijs/hapi/graphs/contributors -Portions of this project were initially based on the Yahoo! Inc. Postmile project, -published at https://github.com/yahoo/postmile. diff --git a/node_modules/hapi/README.md b/node_modules/hapi/README.md deleted file mode 100755 index 78ffbc3..0000000 --- a/node_modules/hapi/README.md +++ /dev/null @@ -1,15 +0,0 @@ - - -### Web and services application framework - -Lead Maintainer: [Eran Hammer](https://github.com/hueniverse) - -**hapi** is a simple to use configuration-centric framework with built-in support for input validation, caching, -authentication, and other essential facilities for building web and services applications. **hapi** enables -developers to focus on writing reusable application in a highly modular and prescriptive approach. - -Development version: **8.5.x** ([release notes](https://github.com/hapijs/hapi/issues?labels=release+notes&page=1&state=closed)) -[![Build Status](https://secure.travis-ci.org/hapijs/hapi.svg)](http://travis-ci.org/hapijs/hapi) - -For the latest updates and release information visit [hapijs.com](http://hapijs.com) and follow [@hapijs](https://twitter.com/hapijs) on twitter. If you have questions, please open an issue in the -[discussion forum](https://github.com/hapijs/discuss). diff --git a/node_modules/hapi/images/hapi.png b/node_modules/hapi/images/hapi.png deleted file mode 100755 index 92938ede712083289c7335d25fe5b1b229bbd467..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42010 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 M^_5D!lI{Ed2bx`WTmS$7 diff --git a/node_modules/hapi/node_modules/boom/.npmignore b/node_modules/hapi/node_modules/boom/.npmignore deleted file mode 100644 index 77ba16c..0000000 --- a/node_modules/hapi/node_modules/boom/.npmignore +++ /dev/null @@ -1,18 +0,0 @@ -.idea -*.iml -npm-debug.log -dump.rdb -node_modules -results.tap -results.xml -npm-shrinkwrap.json -config.json -.DS_Store -*/.DS_Store -*/*/.DS_Store -._* -*/._* -*/*/._* -coverage.* -lib-cov - diff --git a/node_modules/hapi/node_modules/boom/.travis.yml b/node_modules/hapi/node_modules/boom/.travis.yml deleted file mode 100755 index c84aade..0000000 --- a/node_modules/hapi/node_modules/boom/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: node_js - -node_js: - - 0.10 - - 0.12 - - iojs - diff --git a/node_modules/hapi/node_modules/boom/LICENSE b/node_modules/hapi/node_modules/boom/LICENSE deleted file mode 100755 index 3946889..0000000 --- a/node_modules/hapi/node_modules/boom/LICENSE +++ /dev/null @@ -1,28 +0,0 @@ -Copyright (c) 2012-2014, Walmart and other contributors. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The names of any contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - * * * - -The complete list of contributors can be found at: https://github.com/hapijs/boom/graphs/contributors \ No newline at end of file diff --git a/node_modules/hapi/node_modules/boom/README.md b/node_modules/hapi/node_modules/boom/README.md deleted file mode 100755 index 43f1562..0000000 --- a/node_modules/hapi/node_modules/boom/README.md +++ /dev/null @@ -1,583 +0,0 @@ -![boom Logo](https://raw.github.com/hapijs/boom/master/images/boom.png) - -HTTP-friendly error objects - -[![Build Status](https://secure.travis-ci.org/hapijs/boom.png)](http://travis-ci.org/hapijs/boom) -[![Current Version](https://img.shields.io/npm/v/boom.svg)](https://www.npmjs.com/package/boom) - -Lead Maintainer: [Adam Bretz](https://github.com/arb) - -**boom** provides a set of utilities for returning HTTP errors. Each utility returns a `Boom` error response -object (instance of `Error`) which includes the following properties: -- `isBoom` - if `true`, indicates this is a `Boom` object instance. -- `isServer` - convenience bool indicating status code >= 500. -- `message` - the error message. -- `output` - the formatted response. Can be directly manipulated after object construction to return a custom - error response. Allowed root keys: - - `statusCode` - the HTTP status code (typically 4xx or 5xx). - - `headers` - an object containing any HTTP headers where each key is a header name and value is the header content. - - `payload` - the formatted object used as the response payload (stringified). Can be directly manipulated but any - changes will be lost - if `reformat()` is called. Any content allowed and by default includes the following content: - - `statusCode` - the HTTP status code, derived from `error.output.statusCode`. - - `error` - the HTTP status message (e.g. 'Bad Request', 'Internal Server Error') derived from `statusCode`. - - `message` - the error message derived from `error.message`. -- inherited `Error` properties. - -The `Boom` object also supports the following method: -- `reformat()` - rebuilds `error.output` using the other object properties. - -## Helper Methods - -### `wrap(error, [statusCode], [message])` - -Decorates an error with the **boom** properties where: -- `error` - the error object to wrap. If `error` is already a **boom** object, returns back the same object. -- `statusCode` - optional HTTP status code. Defaults to `500`. -- `message` - optional message string. If the error already has a message, it adds the message as a prefix. - Defaults to no message. - -```js -var error = new Error('Unexpected input'); -Boom.wrap(error, 400); -``` - -### `create(statusCode, [message], [data])` - -Generates an `Error` object with the **boom** decorations where: -- `statusCode` - an HTTP error code number. Must be greater or equal 400. -- `message` - optional message string. -- `data` - additional error data set to `error.data` property. - -```js -var error = Boom.create(400, 'Bad request', { timestamp: Date.now() }); -``` - -## HTTP 4xx Errors - -### `Boom.badRequest([message], [data])` - -Returns a 400 Bad Request error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.badRequest('invalid query'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 400, - "error": "Bad Request", - "message": "invalid query" -} -``` - -### `Boom.unauthorized([message], [scheme], [attributes])` - -Returns a 401 Unauthorized error where: -- `message` - optional message. -- `scheme` can be one of the following: - - an authentication scheme name - - an array of string values. These values will be separated by ', ' and set to the 'WWW-Authenticate' header. -- `attributes` - an object of values to use while setting the 'WWW-Authenticate' header. This value is only used when `schema` is a string, otherwise it is ignored. Every key/value pair will be included in the 'WWW-Authenticate' in the format of 'key="value"'. `null` and `undefined` will be replaced with an empty string. If `attributes` is set, `message` will be used as the 'error' segment of the 'WWW-Authenticate' header. If `message` is unset, the 'error' segment of the header will not be present and `isMissing` will be true on the error object. - -If either `scheme` or `attributes` are set, the resultant `Boom` object will have the 'WWW-Authenticate' header set for the response. - -```js -Boom.unauthorized('invalid password'); -``` - -Generates the following response: - -```json -"payload": { - "statusCode": 401, - "error": "Unauthorized", - "message": "invalid password" -}, -"headers" {} -``` - -```js -Boom.unauthorized('invalid password', 'sample'); -``` - -Generates the following response: - -```json -"payload": { - "statusCode": 401, - "error": "Unauthorized", - "message": "invalid password" -}, -"headers" { - "WWW-Authenticate": "sample error=\"invalid password\"" -} -``` - -```js -Boom.unauthorized('invalid password', 'sample', { ttl: 0, cache: null, foo: 'bar' }); -``` - -Generates the following response: - -```json -"payload": { - "statusCode": 401, - "error": "Unauthorized", - "message": "invalid password" -}, -"headers" { - "WWW-Authenticate": "sample ttl=\"0\", cache=\"\", foo=\"bar\", error=\"invalid password\"" -} -``` - -### `Boom.forbidden([message], [data])` - -Returns a 403 Forbidden error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.forbidden('try again some time'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 403, - "error": "Forbidden", - "message": "try again some time" -} -``` - -### `Boom.notFound([message], [data])` - -Returns a 404 Not Found error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.notFound('missing'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 404, - "error": "Not Found", - "message": "missing" -} -``` - -### `Boom.methodNotAllowed([message], [data])` - -Returns a 405 Method Not Allowed error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.methodNotAllowed('that method is not allowed'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 405, - "error": "Method Not Allowed", - "message": "that method is not allowed" -} -``` - -### `Boom.notAcceptable([message], [data])` - -Returns a 406 Not Acceptable error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.notAcceptable('unacceptable'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 406, - "error": "Not Acceptable", - "message": "unacceptable" -} -``` - -### `Boom.proxyAuthRequired([message], [data])` - -Returns a 407 Proxy Authentication Required error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.proxyAuthRequired('auth missing'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 407, - "error": "Proxy Authentication Required", - "message": "auth missing" -} -``` - -### `Boom.clientTimeout([message], [data])` - -Returns a 408 Request Time-out error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.clientTimeout('timed out'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 408, - "error": "Request Time-out", - "message": "timed out" -} -``` - -### `Boom.conflict([message], [data])` - -Returns a 409 Conflict error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.conflict('there was a conflict'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 409, - "error": "Conflict", - "message": "there was a conflict" -} -``` - -### `Boom.resourceGone([message], [data])` - -Returns a 410 Gone error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.resourceGone('it is gone'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 410, - "error": "Gone", - "message": "it is gone" -} -``` - -### `Boom.lengthRequired([message], [data])` - -Returns a 411 Length Required error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.lengthRequired('length needed'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 411, - "error": "Length Required", - "message": "length needed" -} -``` - -### `Boom.preconditionFailed([message], [data])` - -Returns a 412 Precondition Failed error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.preconditionFailed(); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 412, - "error": "Precondition Failed" -} -``` - -### `Boom.entityTooLarge([message], [data])` - -Returns a 413 Request Entity Too Large error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.entityTooLarge('too big'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 413, - "error": "Request Entity Too Large", - "message": "too big" -} -``` - -### `Boom.uriTooLong([message], [data])` - -Returns a 414 Request-URI Too Large error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.uriTooLong('uri is too long'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 414, - "error": "Request-URI Too Large", - "message": "uri is too long" -} -``` - -### `Boom.unsupportedMediaType([message], [data])` - -Returns a 415 Unsupported Media Type error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.unsupportedMediaType('that media is not supported'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 415, - "error": "Unsupported Media Type", - "message": "that media is not supported" -} -``` - -### `Boom.rangeNotSatisfiable([message], [data])` - -Returns a 416 Requested Range Not Satisfiable error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.rangeNotSatisfiable(); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 416, - "error": "Requested Range Not Satisfiable" -} -``` - -### `Boom.expectationFailed([message], [data])` - -Returns a 417 Expectation Failed error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.expectationFailed('expected this to work'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 417, - "error": "Expectation Failed", - "message": "expected this to work" -} -``` - -### `Boom.badData([message], [data])` - -Returns a 422 Unprocessable Entity error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.badData('your data is bad and you should feel bad'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 422, - "error": "Unprocessable Entity", - "message": "your data is bad and you should feel bad" -} -``` - -### `Boom.tooManyRequests([message], [data])` - -Returns a 429 Too Many Requests error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.tooManyRequests('you have exceeded your request limit'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 429, - "error": "Too Many Requests", - "message": "you have exceeded your request limit" -} -``` - -## HTTP 5xx Errors - -All 500 errors hide your message from the end user. Your message is recorded in the server log. - -### `Boom.notImplemented([message], [data])` - -Returns a 501 Not Implemented error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.notImplemented('method not implemented'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 501, - "error": "Not Implemented", - "message": "method not implemented" -} -``` - -### `Boom.badGateway([message], [data])` - -Returns a 502 Bad Gateway error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.badGateway('that is a bad gateway'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 502, - "error": "Bad Gateway", - "message": "that is a bad gateway" -} -``` - -### `Boom.serverTimeout([message], [data])` - -Returns a 503 Service Unavailable error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.serverTimeout('unavailable'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 503, - "error": "Service Unavailable", - "message": "unavailable" -} -``` - -### `Boom.gatewayTimeout([message], [data])` - -Returns a 504 Gateway Time-out error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.gatewayTimeout(); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 504, - "error": "Gateway Time-out" -} -``` - -### `Boom.badImplementation([message], [data])` - -Returns a 500 Internal Server Error error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.badImplementation('terrible implementation'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 500, - "error": "Internal Server Error", - "message": "An internal server error occurred" -} -``` - -## F.A.Q. - -###### How do I include extra information in my responses? `output.payload` is missing `data`, what gives? - -There is a reason the values passed back in the response payloads are pretty locked down. It's mostly for security and to not leak any important information back to the client. This means you will need to put in a little more effort to include extra information about your custom error. Check out the ["Error transformation"](https://github.com/hapijs/hapi/blob/master/API.md#error-transformation) section in the hapi documentation. diff --git a/node_modules/hapi/node_modules/boom/images/boom.png b/node_modules/hapi/node_modules/boom/images/boom.png deleted file mode 100755 index 373bc13455bc0a71a6a4538158aee59c6994b761..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29479 zcmX_nRal#C(`}IA?(QuPMT!QexVux_9g0iPQmhm!ZUu@2cXxM+y9ReHw!{1V*FH$X zL9Wa^Gi%npX6_+UMM)YRg#-lv0HDjtNU8w8=!YmpG3?_c$V#GxO^&N8}g002hs z+Y2U%8G{r6KvA}lkWf*vc5-)evvzW(l9iC4a&~pHw6V7U0KAqm)vYwt4+wwbiV4_CGlKV!TyNIvah5h+6Jn3N0H@Mi?plEzm7PRju3y3?^ zd9fk+-@Xq&Zu;ii&9&a`jlI;(3q#7TGHWIfJCV?mWw=y71)&v-Q($j|4D|MI?y!l1 zQ0SZiSV%SI)NaqTFo632Ads1+6R{lt<28ed1n5*u@BBy>@rrpUo@xLS6bjSn9?vI_ z6ody5^@$ZP1c*w(1ZDpEpbp4^2YeYZGu;NLumZl&2ky-Pf->(@ePICliPZQoIq?80 zT#Ij#0Bb=&*@V{j&j6i|06a_iUVgv=E8wH7wxtZ9vH{RJj)htcKtcn2RQ(pl2!Qtm zd>N#r^#X*Z0`R0RwSgDRNf7wezt!I06yK_Y_xCDfjA98((v~i-J{nE1!NOHkwZ;a_Tr?U8c<)K$Y*GJ zWlfuOnDDk$aa>|0)1t393uq$6e=_#HpMEvpT4#BL6JGxWsI(P^@r`HwV`v6h;4Nz$=t4A+PZAOQf9IUuG= zG1BWUB9=}BvaWY4U8qlActXYLdb`E3#8J$H$XvfLmIaG5gpXB{GkszID@xAYscIdb z;Eci6t=WhnSO;mZp=0%1JRqdvyN%$jQ z`=J^8p_j;%lOsY$hJ|(xCk~e#%lDf^FE1TVqy#5@(+^nLs^1#ZIMY(oj%u_AEXC>E zG9SJv&@Gq&w7?`Y4&EqAtJh)wdYbhHd4Dcd>T4cM&Xp zaf)f?r>U*}$<@IA6sIQ+&aGFgP>uM5%k7cIKNdnDD_;Q4OPV3ECbYh@sn~aK#$HXL zP)eE9o*p@n-cQ+wyY@sw562G~_-4gGoKA#DWJT;rRPjrpka#AFctGPLFUQd@NGfKk zlco++J(C}P{4h$AT+)XmQYLnd;*!FWwGvd#E6ov&xMCx9|8gl!F7@qVgvUB1)|OIBAId4$ys$M9}R~=uwvVt(sG1yxrPQg=$7zD4~+#Tz&~IIWFxQwW~x+5yb6ZF83MkO2`m~qLizE?`wExj9ZMP zh1?2F92N$4CCMqtI;AqDs-@CLZ9L^CMVWHJJkD|SeX)9HT0GDoF=p-_&58Mv7x# zeO{*kMM3Xjtl%O+Vjz9k$9o??>W)|ufn|%^>ctbW=$s}oe6hG-aPV#ynA&>q_y?H! z4)SX}e%uBlOeJ7{ZW7UC&m^iR0F6E@B1}76B-Z(x4#^Zp$|ujM6$!U>$$yf`l56Q! z9LoF^ta6{2giF|LflIv2+|45WY?ivCvpShNvi9<1{A^6+JdXD5>rW?F5nGvCsN24T zzt{&2oxO9%yRXBF2#VQoSOk(q6}~C)C7z36G5sNket(JU`92oKyPLe*iiUlPXX@L6 zgaH$U(xnWOqR-Fc_|{L}bbVX}EW1si^u<3~70?w{(*?2!(!NqTa0&^uafJMg|KTED zLamrkZ*^$3XZdxc%p$D%rOz>{ft?}=amcRbN7*}FR+M`2!hH=rhIuB$YAXwE%Z{%!-8h>+>kGo=wOPq^_S(v9`Ky60-peT4`0tp*wGhgH zjo<5;9A=eEPqb6Y1KK|LDB6LHx`uR{}SP&H9@!~Bm{=1&Zjb=Y;+>rDQIXOarz zM}9BITP94w4_sha@!BPga2oDNT}iAhF70hHpRk;^JlI=f&C+bf=im-`{f+`%VCieLZ`mf|4CPmH zD{^*Q@wCe{sdV+UM}1TMX5~@gsky^7pC{>MO3Vyypsu&vmBx_G(n0V{g4N|jbY@bf ze*oLV%9rK5dS8gy__{5o(^)f?`{wlL*C>c!tKhi7WuyCL_3|#RcB6J$g@Cccq5C25 zC1FN+pe3Uvt-Q&=uIbdLt6vpiwIY3o5Ee4=5`PniDe*2Y zHEtvvJ^Uz(Pne&7OT_j0;HgMr!hGUG7U4_Y%SbsP0eisx?9u%A)UT=Bl*^Qa4hO%2 z=fln;;)><|?tY5)Aulctqie0llP=E{Px7<;bxh?QKdL~6SL=tW8}-Se#{}YpgjaaD zUsq3NT&&Aby-8&zqoxP|_`C-Ifls-mkC1R+jZ=Cz{%Z)jKqV29+=o6zbxbx$xo@xpbni)G?vlY5|Nt ze#q_nb;(*6npJjvsjRBfH2C{?V&R+WI(`}BVrkdOOq1{W&9nFEaH@ZUjVnZO_wRH{ZrSrO6+`aqz3{^U46L*dOIJB>3T2Aw{D!8~m zcK#hj+f|E<9as7}M3>I%K$EF-Rg?W39T^!}Z_b&zQt4u*FPv@Ma`Q9lF_uCoxgC<_ z>(i>onrT1MzqBkk{b0(W4^CXZ@I#~y))6@IaIf{$O(yp=)RtuorG(c45|sL6N!RI( zwUi%Oa;2&P2`U=PNp+I1RhF1jyAH%ruqF)`T&PuPDAVD9EOZ4@ zMl@m0rsdgpHzOzuwMt!9J?7(w%!w!{ESKvYRvr?vC+C-=uwX~3e`TfSc2vaqv?&Q^ zOEZQg{!Djlj-*`orZ>yaw_j^bg$8hPeO*~u855A7pPx8lF;`(c(c25(WDu)as-+6n zO8xb#v)+Mar27iURaYnVlk; z3@R2<>k?YImJEFRT%vmrqK4diK={A_ce{3!r$BdVgR3>Ea6VJoek~qDlS~28lc4_uA0m zOeHH$9DYoAyjAKot>PGPp&$^C)=~S{KaB9^Bn<>s3<>10ERk#>V%DtY(|tWPoKy~R z7}6+NEX}0rSZNC{-6lqGh!CTfLWsoM>V;_TWKW6acwFnzr74wNF>t(_LgtGb5!*c741s}mWA^=P&CjBpp(Sy1$GK|XwiM#~EyT)y=AjGT< z@3rO_x!&xIL1*uh5WALYG=7(*-!TAKZV&LUDPblY?2Jo@?9eoyz`y8#+H;>onV;fR zAiCh%+JhQ0w#fJ1->nDc(*TN$Dv2JVip;LVkVb8*-YX*1L-M;F`T65(CNhxKa%8CI z{r(g&SW^te+c~G>_0eUyU0SY50*OPI`3dcR(X$HsB8&X3kq|!Ju)ydt>CEr({fmO5 z10v0hd=(mR-Q7j6IjK-R9IRgfa!}qSvJ$OnFE9+bHB5ZP7_88L%GPgC4=|>bE_!n8|QaZ5(LZPf&q$=vDQ{j;g@LP5m}M`?-$eK zvq09_t{hwm8^zCza!g*KojQMh=>A=IBf-YY$f7`N58Wq9G`7w53t1G~M+K?DsD zHvb5lqy6$JyVfwTR#8!wuqKl*ZNNrnxP#KqBG2-z#RH}KKK0(voE+G~kdGAFSyls^ zJBevhHZi4Q(%9lS3md&nW&S}8^>D6JRECW0{<$!c{;F_?I(9JK>V>MJ4!}=z8z?kk~xb42b0~N_fUDI(Kj7Ku&~3 zTp~iw8{v$NT}tnbKV^=b9GspukJX<9Ctiv%?t(@84AlM)fgA|7)L7yx&i3}l%C@_g z2|RYG_YrG~K%rG7IlX&5bu`!~>&t%0qzv8j(HG*JAx4q13tIRPt?2c^+w(jH!UWL3 zxKCIGVNpxF;3xl{F25Iq&`A=MdW(~@qoc=?@Cj7vuhR7#i1ScJLzCJWeaHA-e0a78 z7x#=$*zakK9OM`%?JH8@bXGLs`e#4L6w6WynbvWS)dvW6@d$!vq26yWMJw0_GOrFb zp1F8}pQz-Kw^o(XYdelT0{+?7^SvFUaihQY$QJ8&jbt41U}<40%n8dO-G> zzNqR|;D#38ezRU~AK`c06A?jyr`AUd$^fIhe1Gl!NPoI`89xa*?@=!&Cn$_0)L6*egx&4Yu1N@qfr9>n<+#0=BzfM@ zAg3o)$SBMkFO!)zsrk0p!M?yVm2H8qBH$v9OpzdSwICV3Zhf?i+Q%p?^y%v==%Dy$ zdhxiFD{_Z0JUm<&Jvwz{;w_PcWrI~LQ3ko^B@q+>_nz`$-SzWUzFx|AwsVUvC`?~~ z=Xn9j%t(w9O*E2!>(q1MFgs3h8Z}`Xq*U1RVKIM8qL316ni6!2>x~~2{KS>eo6E0_ zl0qW2S=?M_MWhCQq*|yJ7sK=Z-aXuZg)3atFT}{L4vKqc?~d~%c4uq!^JKFW>SHEl z$L*I~XNNkY*BAw+8(Hv8Ana#1ViIViHiNPGRkg+s#haeGDA!#EMtI=qL>g^TJ2H-` zCcj5^O3WPEY{W+(V85%ku0=sQ#81>7xU;pch`qFBSf^DH7B4ln&d1{R8>RbKJ65S= z$v-s6Oji(Ai!-Q0HX=)9Cd(oi{^RS;0l&oiT`3QP>!A#k%Fr*FxDZ3b()*iRBS%KX ztEtp@=2$%WKyZPVrjzHL2#%%s?C7pFG=AY%T04?pBK!HfZ12~s)xac%gwT_$0>3w^s(g1o4*AraTh1e=)Rc-@6Ce^0CIN20-^w7o2&jk8y^brhTY6Mn z?bz7Z7f)%YiK~R69ZDHSO76@lbSNn}uSJrLRIA9LCzs6L#iC<&JP+$kzifjPR}v4S zm)PN1PnuF=GN-a4jM+CeUA>ZELB_9PpbmZ<#nC_qaDH($)6Ev%bS%`3Zv_IC>cqb- z@--@R__97q$aCN_R8MckwP;`E+4EA4$9!W~QfS-A72iCZ^?#;RC{oM5^6#)^`>&uf z2x$hYS%B*u7cYh_FRrHMJ1J|Eb0cS-6}c1DsYu;SeP9;n-@7?*aXtY*eOz!lv;?qW zTh&PPvsRR2E)8wNTn@vKO%E_|9NPGbF)HDi&I#$h!mG@GuM%}pWf=;*aoV#P!gw(~ z++TW@j(gEI4t!0pUw$EF++}m~eglxn=P0s~`XR`bldu5i6Nqhs@(I$8{%_Wyt$Q}@ zqSMLcEJjp@wBlzGryE&^9+28`=ewdMA${QlH%S99M0*TZ-V@vDsPB6bb}~AXDEk)@ zc>otknYc^7deuIP{^2pzL|BC9mUP<1asTY-(Q3furSI;!)1dH;mw%<;n(E>wJ5;RI zIIR!dk^}EI>GdMJ^yloiH68r(a`3!omuA$FV8qoj`ISuUDFf=f#8nb;0U_08}a%6MPZ`)0M9=D)y08k z%y$4&cb$wf@L|F~@LAO9jP!RRX4=T?8>_Igy4o+-hYv^@xB1>>br{7QKOD8AL)lnS z_?+=i&U;@)WSg)t<~9MxI#HF1ycJF(@ZVn1tvNiwn*Gjvql_G*jLyiS$byz{1SDOd%1LPNN>AYaWJ4?phxUu(kZ_k~K$Ddp) zfI%Vh^5TyveBHuZu+$gfGw%|g@P!G5&5_>)w{HdBC`m7Xtby;d^Kkoj)MmltZ>l*|M3rDKenFn#*Eq(zTl>+x?|Yzs0&I@OR*AWKAebx7-2Q&B-BL!s%mEvPM#(X zqnhTF_%P4bo&_<1*OT56}nua-vZYtqz6 zf9zJPVd?**FvcGDu|kxHOVCl{1#v*Pwuwb?s(iOpb*b1;=9e;@o1k{bON;C@D^1u* z2qCQ7f4ze`10LJ+V(g=cr6PpwIj(E$Nv}RV z0|jXkOivmrs>c&hCuwsGFlw_eEJ~yDqJ!OSNi2%}Nx7!j#!a3TI=yFL0)hRdDlC*d z7API;eSCjWw9;TUU{yDlLXvCtW~J~u8TeC`PV~^wP-%eQ-74=uq3isM@9PJnUk9c% z=ST#T7&-jbp_MUP*XLf?sD3+yN>_v>~hzJOP5!%wQ_yth4 zao2X_Z9I>Ko1f1MY;`>ru+W`5H#8Q)L%#`7G?+S)P?4i4@t{PzY4MSzYLc$(w?QUGQE>es zzb67i=(fUV?lM?`kP8%NTR=pH{WZA+B2}DHhzu14T2mRB*nA`O9^w_T+RUmXtI{QQ zpQ>)xD$8SqYbJ|r`Wi324E5Qq$67vMfceXAismYeo=K>CF-PN}5;PpuUKYV?{OAOPDztu z{0Lg}C~MeG+?)JWbr4dR_(v{&df!N{XQp`?{a{!x;%lc|uShRUV^-L=-c?WK6JMUx3U#0ScidJ1`$g}eH8&p%HdDBLulNZW+P<=1a;%zTWnPrtZuVM-cCf5afWe=ap+T$`!;9*lzI&fK?& z^rRQxS&_bwj?d%{TOsFt$&mUIlj|-#!o6=#`t6_-f_~z!;okX3A6FK*u^I8|w){Q? zNJ^AysNG;N_TjC3Sa`0|%29#=1scnkXRTKi3fgYtI&Ftgr% zkbYJds}eQouX>!I(oYG)kTLR*);j;7r|WA?M5tr(j0FXCS(%nX5YsmXNQyCJO4@s( z9&jmh3cPCxbpJAuMgOWhPg1UInTn!Un%`JUcG$=Gq}QdO3U*J;$FF-LQfelrKKWSp zL?%8kla_~a|C}{@{3qppbElUXg97NKY;3&VVZT@%X3rC)HcVy&^`0;L^LV*o%ic9~ zj?%y8|Cr^yeA3W%@U9qRZF)*s*cu$W)m@F$DlmIsX6?YVk%8%T!+Ens7a1$2w5O3N zzt6y_^AzY$>V0|TSIB-5v1PXRnpF(uYA3%?(}_!193r)Aa~Wk^1?iGDhsoALXntFtyQ$2<5Dwt@{qZEfF?BhK zB^P}8bp8zW(h{TWjk6#N6Fze_B$otO zeuV||SAM3qT8L^q%f^E#KqKSQvpM`;7d*P^xqdTeSJAX5pU&gZyxO}9ZBu)^SzKSv zF<&dIV5E>-!@A`Q<1n54H6c_-CqxOLb%BGe>Fx@=KMLe94k#~~6*L1CNzitsOcH@4 z;{(2^>bq-wjE+VA&I##T0qI!ESJHWpY>KEpl)XWyitX`ca`o}`onUm#t6lC@K5K*U z{$q_W9&_K$Rjrj$sldY7on=rY6EE#V%DB?ovtGGGD>f(fiA}02N}RZw$z1t)uooCh z-f`OgcosNvm3`ORaRHnl(|bb;Ym|w{js!S=y8q6sbfdM5^1HCf}?^roMB7v}i zhySX=R#s66Rf6xL&B?ij9i-r=jhckNrynJy*kSW#>+G>b%f6saboSUpp1N*2NAG^53{(J!>ih`a@g4P^R--5m z0<}|Ak+(@<`qbuTl&Agr3v=xDFSs{N2cf=Qv<Iyls@V`K5*Rr z$T=nW`ew*kM9MX8e#e(5%MHc`74wvw(r==7oPB4puo&R|dV6yAi;T48QfSqVsMhSS z{(B1pnZz?Sb|tBh%y@o66j-EI5~!Hhxb$|AIA>0E>>n7IClherZ}tMlCSGDky@gPV z=eD!6(`J2A&uxHQ#OEm!3b&(i3bX;6|ti) zKHr_>w zGKaYy{m5D;z)OSwNpC4|zw|dAJY7#&W9xh#1bN&$e}nl0jVlJZz%>I5^`ze2vDbd? z`uYx?m)!uB91^fVf6$m_5~RG5PUA?(MpCfn^h%{yE^l#=hBFr*ze$>O7T9+eGyHat zUPc?x5C>5jwU%+!Umyg3nHkdbH@fbT;Z%LVsKus1WM%Yo127^j;3W?EK`D z-y8hE_?8UKol{qF+1Np)_?gptCFaRnJ3C3cwie(yk^;OBJOghT6~2YiozfF+lEP)% zvZJpPSjXUIZw>ug55ufI!Xh>y_nm40d9A>du|qk0(EE*QbCRNu$t1+2EzLjKURRLF z-YQjDa{L(G5T)y4b8~=7b$QHvgA`=O*Aa#Ty-fHmuY)JITjV>tL_aGY z><^`D=o8Qkco+h3F1+T)5h?C#atsb0YI5ZxQNdep(}Y|dBTduQ`7`8shv` z_zC&CT}4A#DF|Ezy!B>S9k!-TTMbD5Frfd>CbRL5ecS!kHE+jjo5OssI@$t8mKG~J zh5H6>qb98@n|nO%$>;cO;k4RH8EToLnGlntwQ85xg7KBOn*&B>R(9Ue30I^NoyJ630u(8TTA$ zrV7P{b%vBF{qE%Cr0t>OoeB#mCMQWEHVn(Upm=W}#sghuL>DiW)H){QOH4wJ7F&fp zUBW8#UMCge5`ne#+-b5wJKB=c{6;(D;cZ7CL>^rvgkv3|Q}LtzZ6q7jOkpJzc2f57 zFz~vVOfStlB)jfg42iF3w!6piw9*KyjL>e#@gK+&#tCLg+1svv;V<-;(x_Zdo9@@U!&! zH?3BTryuIys)2MN`$gnD-3p6OY6prWi5kgq1>uh7k$PQ=fjj-myr1_4lz#mCBGq_%=#7UgzmXNx0d$Bj zyA(8u^Kf|y5UB|Ztg``h&f0a70I#fh3tg=VSYFcXp637IX^eSKO<(aEA7^xE~=@ZU6USG7?oo9yl%j|&s|MQSG)Y_XqRtx2zw{n}& zj029U(lqk3UEAab)^@FNj?;N>7E!F)7)3>)08skaxXCJ`nfe=af}!(Y`S2d8C{%K) ztP|uShSA#DchOQZkRm*3CyxIK(hQQ;38BxD`AgXNAQ^Jx zExM@lcG^Pmm8hm8{snpJU$q!Bi=bGu6S)kkL+JRs$b?b0X^kXvtF~^3q>KeAz77pU zKWf;4dirFU9U}HvD9*X%cj$g1?=pvpS0FjXstH$VAQorUQAJNSRZhwXhVRl5khuYm z5dUe|pfI27D(|bgNWf?y#IiYCk!F^29&En_oF(2&zg}P})h#SXLo}}~&V62m`7-p-lWw+RT|&ydO4Ar%%21dO4vxkDkwlQqprCeR$Oc|>LR4!tN()N&8dW(t z-!q`A8020TQN~ZiL3Uzs^Kz~JTUZ`oT^G<`s8D&C*LR)fk&HQJvX~D9@|)%@Q=o<% zhdwNLy{pt|JRAIvUf%~nm3$jSIjp5?t20;5#>UwVovTi@Vnx_clF40cCB4Vpn^Qk~ z!s2ghYb()UdsWfVdWSXfu0F->Y3(n^mJAN_RDM1zbX0GGE4@9TTLmkPBwOwKsoRwR z&%O*)_WnV)Z4|r z$+%|eK-F;*i_8!_YfXS|7wv2(d))oTipJV&f8jjO=IVKJa7Y_xDh>=v;WFHddtN~wAE`T>!s%OB<(cya^?`fH6A}4z zHx4rcbj=Ja*d5wpFLN;NGD~g%=(r5&eCKj%O>;B(SgD<-p2kLzkayj%O_uIy=U@tv z;NmDfd(b_NJ!UlxpfA*C{+L>iUtOa`BxvD#7bH24sugXpUZd}5UFXVldzR|#4o*&< zWj`b}LwD~Z5rREB)oZsx5~T0ry5Ucz^>jlD)fO(ei?cl9h$PX$Os-TE6QQ>_bHUZc zRM9myxCF-RkVY`D2N!AENl7t1E$JjbNTFc3O2^&_NI_2#$9@gr<}|d}a)ENoOuy$w zgYs1~;N?`DAE|zuFMeAB@o28>VX3#b_X4F()_3j7;j2|fA5o)x&8FqkC2=^+P zw4fz@5Tw%_rE%uNln^ncN2_Jt)N^IHVQs1uY)3dh5Xn+1Qnl?;wO&M+<4}hl@431_(goM>yDStS;{B30yK8yV zUK;MJ%!h<^J|5uH`2;3eqbs^exo+xYzPc*R8HI>Ubs%lW&%?LNQNWZIrO+p=ANFU6 zU`Azf7+QBdr45~Fnwbvlco}w`4eRb(I-X#W3<0^m(hG&|gFnWNfFQNn1+nuUX!|&i z6A7L-4bDzf;2QVWpg45fh0{p4=cdsnB6}5{xgjNV(E~#;+87uw*KXO523YVWI+ucL7qJfkZ3m)` z(0hi2QV@N%S*AQ_9_Dpwt7BKOQ=*gn>Y;L_!HKeF1UhG0fUchLZdK`kvCsjMa1u!$ z)octmE}E;J{W`RA)?Kxt6($*KQDnZNP0n>-kH|{uYJX6&;(r&5phh0jEAVfstDCDB zZ_;M*xJ3Iw#qpOsQj}z45jJ1VD+NrMxoc}p{`Oj~W~ok_&!h^}2E1pd1OOHCmx^>>Un2Mr=jc*5iY9Fza zy1M||W{oHPg~-_@URKSJ*Puy|A@dn9B{8Iopej=Heu5Hwk82f)mu$$$y*E$xW z@W9Yk*j2z`tyz`yT3nJ^-BEeVX}U<`Zt@7q6m7BRuzEG(6OMDm*=7IK^ON1{2S>U3 zcy(qvB3-Bqpv~l41daW@GShIQ{bQZh+k40o(;1I6y=wQ(10yG~V?)CQNhr=i?b0|* zwp}MmKzt?A7iE^OR#@&A%()lx$ImdzziWpHefS+MhPb|B##W<7zt zbek=1pC+v5Hc1^cUrxQkAllA=4bf|>E;3uQ2!btg?lmoh?uE=ixNv>**Os6PKoP>{ z^2~-oe!u&3S|cp+N|V)QrvTgl2%q!2IQJXGsT>z{EKFd4o4v^EWCsXRBrsSEP(H$) zF<=#%EK&LSUI5W$nq0$5>Q9Q55?(f!X;CT;;?I*dX#OQ!nvh_n;T)#70vd*ml_;(B z>7G~J{2Wovb6@__3mt%ZxC3+e5lQ9}vCN#Fu%=hVqBo1MJXGs*x{b z0t5fHJN-M`rd*Y|0i=RNf-IkiyNQya|C#ZE=H-ui{3^AP{$#4P&|1p9yruf?B@}BR z*(31va2E4K@ayqU)=;tZu6%?#Kxa;MQ-PO#shUIkWUjw&e59q0EW zFAnpB3cJFFW)uTHRrG>Qa4X2XFv9CDO~slmxKmYBO=ei{qCB#P?n!_b$A^4Yx0O%q z`hI?D+1GQl-ZM5XZrgj!^y#luO=;nta}DJ;$IF_)TkPAsgXrYrGA`zS(bB)jbfbV$ zP5a@2@C$H2Q9k_!HSA80PShX>_MQ|Ap?@b=o<(v`C%E%2&*BN#Ru)697d1cWwce`k z&3dlf8Edg}M;cTiC7${jm!FoFwu28K!{25xQ^>yVeZ25Kp|eEhFECAx&V7q%<9R!R zfw50;`EjU%A-4zlOp#?ZEWsXn`|B*v<&^{!+sL{nmpW%rSdp=bw?Cp?t3wGjNK8gY zsl@&rx|5j@v1r74eiR>c!GCpKOjj1;M&`A(oATNS20OT#o5NS}X||F2yJiOb{Zhq7 zLdW)wZR@vhAbHHd1GgiA7gi(reZcj#h9OMROyR!N3kktTa>>w6#PlP=Hvl^sAr*TlzoRF3kKZaToIh9rcwyFcx1IwCP2TO*d~SBnbhXP)A3QidehMRG9ihRF zJJac~nTfkQUG<%@n945}=n++qG;afcqRbMOQe=Lqbo-WuajvDer-t_{8cXMbZpiDW zq%S2%zpE7Qoavok1FYWXkU!W!D_lM$pklKpoEDJ0@Z#u;YT+L~YG<;Snvdg%^l>g` zba!^>I-hZsG{Jf`mh=BSj@o%SIdSIH^~gvRhx~j|Q<=$;%XtCWA4YAh!{}Eb07^i) zkTM&p7?Fy%8TVuW*}e7`oD3bd#Nvdy|6E!k1EaBbFeKCpb{Mp zGDRC-tb~)X@#&IX`9m}F`!0UEIs52wfejnItEz+Tr>?)MEY#3`gHF1X(Ny}~X5x1& zok*6Ua_VXceH+T=P-v25jwI*pdu-ri6X<3duv2AnYbhy4J`?a6m+su>7n>R6;-|R$ zE9oz4sV)qXrPdMRzV@c>m1#2?@K}{*L8Yqe9=jur=YBR#_+X!~mn!2lFjvjHon=((1eaD_zMp0&SJ!J(b8zKb|)xf1K9Jc6;q!8Ab%1zP$8I z1fIHy7=yJ4nF*|t7reg=kMD=SDr|r=_;CZPB5^H!S_P-`31Mk)64_xKV}T!9QoOUH z$@O|LVlJ~jugqoR_OpCq=E%*iw3;*ceDx$bo_ZL3->$6ed6zX(Z~t&A1YI2|VGX68 zI3%-@$#k|o^6q2}lQqJJ_p1)X^-u2c+5j8mx*duVBa_gl_C;Eqm-5?&A-BrG;47LL zelwNEy@i*z^p(9XgK6UH>MKIQ3kqQFZ(!zM<8=8^rVSYi73+`jLIYdZ3c~{}N0OJ{ zG*3_6QeNCTIV4`!7|xzH<4k02=WK~gXw@(PBuqPsQQd*^gnCXNs_P;jQzc=ykgGcP z`LS82?7QSl_9qi#c9{0ACnll^<(<~cqzd46`pL=3ta89*Lc_Y--D(9Nf|hZJm2~DL z;f>!$`Yy4NaD80dZMjtfzLmH)Wb9mov}OBuOC_#@R~?O`H$p`QEmEt@apwbNLw*kn z{Rs7H8$uBnkzDbPwZ0R&E!?h}y6LbTF?jEhMS+}=)8){cFU_Tm#GbAYa0_j>wul8| z*WG6nuT~8qK(6z;&dgA;qOtF~_ZAz0e7c0Y;{6B#sP{M4l@HfA0njS3TQFg3P3XI; zZ;Puenq8oAypruqAw0+8tKfEhtY3B%yi%{Q*j%`6ctk{?SP>HNdBC4?_Ah4y>E_}h zW}*63WNe46ISNm=fQ;oVQ!!evAe@sV_+CiV&T8a*#XP~c0j;(a4H-QZ1j=MpS7R-1 zoXcoxscc*1Av%%n3?#LBy=O4`NX-RfV+D+BLf*fO*0*KjJ1Xt${qu2xV44f zz6;r~PP)HO+JZke`cgyYn!O`4QreC!tcW{4JwHD~ujwhRF!NGt={a4rd`Eq$G-b#g z4kO90b@t2h1?hRx`9{=g z3WGN0DtgkhQG}j8!>~)NQL^h0%)+>ff^PVE+(O|DaN5NI*3>Nqj3dx! zx7w^u5f9j3w%ErHa%BqC?gq9m%=&EWO37BcAe7Cb zhAZ;@&LnH(o{^?zNVcT&l{Hvn>uzXGIsVcVhE3!lwL~_^M)@9EK;akaKMOnYVRWr@ z{K`?~!|~4i%>3Q6xNzVfH8yrjhYWT8^=;yMm{*KeSD58N!0X7ca)Yt0(K`c0B4lT4 z?0T!?Ns_O>Fgu2UMb3Mj6#!)z$MgZAbIb0?jJ~{(NqJ#<6Gloy(w(U&h&ObJ;~##C z@k>)R7Fnd^xL|JiWqngW1AdKFFH5jX2f@Mam#11_b zq-c&<|ATlzq0kdut&>y;y|G;6yT^-?9*BM1XlHAO3feT-N|Pb4Ye z@#XNSv64ehda;J=@6*(#+>@oT;H@jdFAZVWqgsX8mhQSeXqwy(UG!NdCXVa3hj`Rh zOXDM1hMj)XjQO>r{$okM=!EzuL_BnC;mu>$b7CMx@r*(UGnb-kz%7q2%=HeBO2)>N zR!rHINOVmf@1?tO&fUg38-G^b#+tlbP!n2`8z>GY7{QXZe4o+1ob2>C1)qy(IRT26gtKAL>WmKug+%kJ}qHhmXtBRL}x z=?$3JT_uORw=SXA`(Qw29rGb*1Mh$eUR)1pL`p!E6SuvXHc$zx|7xE~^uZ&zQ=;V) zY=_cDi}l3kd?l~Jy(31qWB7|(ql|ir(A}K$L}Gdn#>k#k9p_mpu=`Xm9wKSwp6QHY z*A59KkLiv8mGU~hEbR354lXR{)D)KFT-0MQXR>XuBf;T8y0gbGh9;dYIiAO?gPw1J z!cK1}wYFd%X9-l|1AFsW{o_I&!Q{Sr;e|AkExV9JeM(Ss-G;XM|F5L8;A*SuwlG!* zQY2_`cPqu+U5Z1n;_mKViWj#4Ek%k4cPZ}f?(Xi~yx;u+8QJ5Ez1P`m&bgkm>kBpM zV@*NPzdxYyha~kb*Tb$dZmbu^UH;PBt!$oWx8lRm5DjW~Iz~Dkh`2g%)(M;S%-;># zm2{2B!0wv>g{mP0WcwHsSAx5vG~yuO3)i6Co&*oHTH1>vx}xm-o@!Ha(IvSuGeR)$ z-*1yl_~UQ2$v+pwFN_|Mh1uPc9d@sQU3|GqaQ@OYTMleL4-XfcJgg3gW~`Ws(h#$r7B3nP2;l?Rrr z;BmHUpVfu6X(#c!lya5M%V1}-`*H*ZN%IlP*y`S<{@()ze;6;;%;l&g!3M)UN8fo@ z_3GFVl)pCSq+Fyl0ph{G$ck}psAN2tawwq!`RpcTZCqgwGv-xTI^W^eWD%BH!o(Cx zCMH1zG_J{?-}`xecibZGy5kX+%WR85`q0abBOWi7nN{$Ho`d6IvEzN>UKF~%w=2-p z?{Oo7nJ&CMisz4^^Hf{d6&-KK-IJC2WquMoJ~#fX6PsGz(+9$DtRhh`KFrTOzpT=u zqX0!UVW&aZ@XKOU6QFQ~jR>)c;6Tch*B&6)FPm2Jkp7ne$W1Q#Tnpvp=)kZ&Gk2q@ z6L<0vq7#6Z#g5l+?U>u_vRuz*Q|?S$^xGVkniW!WO2a9P^iJvO%pIO%6% zlA?^qM&m1t;TY&Q)Uh2_mlEKJd~ZA!+^@zUMWuj=z#E4xxEICb;7oDv#HquQn$}AP z&h#R7Qrft@$ByuReGv1QD}}~U4*wE08&~9zxx47@y>NYyr67P15AkonPxpH-9vGI? zaj;RBaW#`Qx+M65gl9g00yVu_nc@fbCjV+ z9r_ZA;Hhfum0kyCix@x~+2PcO=lvXm+v(i5T4yP0nwXE>~_t*LaJvXdat71^LM$=Jd!{&l$=EwFy$7U|lwi6lZk zruz_vWp9Gj!KSQ(U*xcS_Fvt{746+tNL*d@fX#g10fb_Y_r>nXTk&^DEeO4_nnt8H zbo-Igu2qe63?sg!uyb1sbNIcln7U|{XX+Jd(l}?wy`l1SxyVIqRn>s?{Is?fTh~-Ln}FdAYP`B zyR@oux@yXZSsY^fdy4N_Q&GkzO&9ISur{vtg zR5w3};qHAu#$}yLoTnR_lRsr_czy|PPJ2)d1f;XVEB+G~PYNe6mu$Ctx?c`am&(j_-GYIVjqei7vo zS7hGe?JFZP-=jv3Ktlr7{wSi&SmO*LnG#2RFs$n|Qo*RH0c})u(l8tD&FFr>gJ950 z)HSp`e^Fw7xwlHhhdky=>yX?kqNOvL4SJpHB5MEtP1K9yg20tGn7zBiIl*+WX&7$& zy3uC2zVdvv9OC=(-60k5vE&yi>4CJZ^iu>2BYqe@6XNjRX7P zfuO2p=0J9%RxUc`=ZO=OUoCszXt*3=@>Y0QtPG<9giYD4{RFv?*3K?B56q6 z$PVHMNA^444FL`IU)i>)sc1m8|rH(WROAp2Fb@>W?L#m~hUv;dug>Td61TmC>55lnN)@3xJu+9`v z88`01{p~mVKRVPToHjxgN;K;E|3uR+SxBR~Hc1yH?)0yU#*^xIAn2IpW~bJuvq)UP zIH75Eufz)3uo@6rYW#Q#NqO{y)nOQ1@zsBf_cVDXVK%q{<`%Iu&04J@iy1c&UNmH60)%eoeeFNn6=sORj>+Q z6y4XYs^JC-d2G{4qxmH#4B;mM*~1X^?O=o!K^Kf-Oz-7>VoKx zh<2jq0Y?`pPf<6I_GBXJ*tB`x|Jn+|-$Y(@d|{{;JFOSt*N(xPykp~ZB2SZK@n_5T zU=HJ+f`*ebJgitf)VSNf`+aaYqtSOP9EBS(hJe=CTmq5{tBmIE-wCB$@ z^H)`8@q*veku?;n!(%U#AEJq2W8iwW9RgLx%d2!0QLFM(mAD{d)IoC~WQsn(bHth8 z@RLwyL1%B6^-?^|$=!0)r3lgZWeZORlkMQoNf_TEXpvg_jkVSlo;?C_Qc>2Pe=(h4 z9^QI7u6W)VeZCjj|2an|f5jG|GZCgvDdr|^K*B;*$B|n?(jzlPrs6Ee(VY^BMwE?U zd&0Xq)rSQg^2wZg0OkI`Zu%)1zn7pc#{uM)GseOWsYc=5n0;_AAGt5_4p1AE*r@sN zK-0yW4x)BQ^Z*MBNCoDFp6Ptgce|+T(k{YKxpx;`l4sW07#Mg%3SRs7FSnT7>tY~* zN~tpTntqJSfD0PZJx;ozzUa2%yYo<0 zZOWNBI;m$~sbwjmD8WVWHcKM=&U!J7bBPmVerS#P&;WX;SChWsk;JNV+&vxMp|Ac% zz15@Z#(nU*9qjqohVGg`qc~e`cV|&>C7g)k1zuWQPEC${I-T<^$Ek08mBjGUrv3~6 z#QH|FuoKV41FGnb8KCIm`eP)R&HqpV704%Qy!~{W+kQNdAo3~x%t?X8#iEVZnn}4U zE|=hI%A7_Be?g}dv>{~M#L@2c9DHOIsn}^!U&;sb8dM>ao*<;rsOgg`REq;R zn}{OJEKy@QJ>=u+R>G|Rkt+U;0@8b83&-TcG7;7Mz50%Cr$z8U>sG9C%xNRi-y!zZ zFgDSs$iS9cvWr&e`ME%eJJncSP@yP^*1SJb4z+-*9p$TPrzcgv9CO!Xa+t2>VopwR zzfs_;=aY}GZdX|e)HA_WdKi=I!kG?4cuR)#hSVt*Z7fQTRp5GjS;Zn5XZv!$Gs)p3 zQ~SbTJh!M9!~?0d7n$lqXR(c_SqJW?a=+1a24X7v-n+ilG#e*e@6d^Oi>>eQqH7zt z&+ebKpSOFSFygg5^ZNddu>cTLP~%%7eUf)GMt%gG2Nn4-1}h9!s$SXRyfA8ZD2qR$ zNn3`N`mHppR2W(yG#Y?p4=1*Jbnq3XjQQ-`w)6>As{bkf1Ojn;Z$^|Iv&Zl!W8@Nz zZs;Qih_ItR(E-``ulkZTM0Gzj=i``@{3w}<`9L~7WV&$8cQ8+IY2Xq(9&^ROV6-5g zK*3yC#RZJ87u5%BX@TvSB`ld0WSGUo`ygSGwqNOwg5Ob}eOQ?(7@jm|;G`|EgoaLF zp{eA+Oyz>J^z?L{xaf2J&wQpzFK1Mpw#cYguT;jm#RarV3n>L2nfC$h;ts#eyT*pz zn}3Yk`64sTy?rt+9CgIzZ_k1%e8)?hc7oaLaYa~X)OG+uOl5<>S2#>Q+aM%DARjzD zDpP>Q8|E#_|z%&Lh68vJLM=L-I$Gl zbW!aOimE)AdF&i&&I6ez`WszZiyd9FV8r~1niBNfulkSj>e8RFA9gf59UA%|=N!b1 zPmSkMSmOoxeyZ~*+Qsy1v^NmyT3YNTQbYh17IxS*2|Ao!SU;O>(ZP=bYu732Q-Z3$ zLP=4S-hy23&+#+}^0v}8O&^rN%VEKY1zxQluTQr;+NGL~pIUh_o7K{mlCG^tVFEsR z;a)g0`)`=sq4C_3gjHdau=rj30ldWW)3U_S9}G6sJMjV0L2S4GUzB)>Vtt(D!*Z4v zvo3go0+H7IV1I!7`o8Nqwz(VU;FQZz1JBfRUv|dNp~1J5?mAGbCvsphOlxORh2Pec zu*9_TE1*GMae>+d-GDL_CRq)qjj_MvRdk5WrZ(u^(n-O0y+-i2*p5*QtqH9C06#8M7% zh{dI{ryE#6=1>la$)={2c#oRebiTOVdN^dJs0!N=^^O5+=QIpVCLkTal0(4&6NRxv z9r{p&%T`$l_SmRvt4Mp;^A$svS&d_L?Z33cFF*J`te~_uN;!f(vG3M1bwkdVuz=W)k-0#KG|D-4)pZ$Dj@CTW47YhM)(e1nDE4-bXwtD$|@l2^kD=P zR&V>G^HqSF`Zm>(gAQ|p!r#wxKv{z4CB59 zjAe3fE3}HN!@d!Ey#oXG7X=aC=kr33L!m|_-Ah59q|V@-Kv;&$=*F-A^(YjEU^cj1 z-qGXTftG92R5tEPcge9Fq3G?8F})^D?xCUUE5iIf(~<=)l%1Z%t$e1pg0|DH*A&(y z%B1B-WZxj3F!T2peoz+7MH|d`ITXd?KL6*eX=a5`vr>7sbel1^#7O1?EXdnyh)#6# z2!1t+Fnq)mP05Yt-rL;)s+fl%A}r7;9>Y0MShV9qMyXWgN;JE>gNSzqlEs!-{^G) z&@D-E@ZBxgR=!F?t)!~c-R6g}lvU0qwC9_&u(M;W16?;%W1v2hyDb|$oBmd?dn$_Y z;(N9dBz|io77c3BcB97^VtARuAIHKt@((|IVp$jjYzX4=eJn~?j>c`kM1ajcJzbZx zs6q17U?j@v8yxBx?So@9%=X#9srrpT!AwLQXsYB0x6$R$y2#Bvo2Q!VS|60 zDbygu(NMReFJy>xRe|Cj;5vrm&SIW}e?tw!sp(aJx5(oy!A#fQju_T%;gmeOb}g$b zZA4-C*1B+q^g!8b6A?n=boT50Ts-fVd#Q0DsK8Bl^*`o7Noc(5gwa(_7j zY2M|+-##He-}^IzqnOe2)R%S+Xz zrKN%VDFm?~ekq#~6bcHO`ecCJ7IJXh)E~?Dc(_=~udr6Z`w<;0_pj`+(1BZ_g8`Mi zNkBiGvy1P?)0$*itS4t?YhzS7OoYvSt{Hv&T4@m8w)(cB(m46)Ze@fyYBXrWCGd=W z+R*wRoQ#ZTD7@&Ta|piRnKRkFU_3OG zx80E^X8l=+X`RPI2g`%^7WR;bNavhNl~eK@puZwRAl>W*jqBsH zVU&Q%kL;K0{r#TDve|gQ(%)2ASTmBNb`__BHl{Z7_jiO7)waA@eKF1~j|)f55!WAwc{H=S;dt+iYRXauR11fS2k`m}i?ZQvWJRZwOPPA#qtF7!N9 zM-s~{&G@A~yF_GM4t=aUbkIs3^?F7^W=F#Tt3X(UE!ktY&fQLlks6N* zbKT@pT+)?>tlQFgj*01rT7hQ$a#)7awlXJ8#3{FPJYiN7_Q9@Bl zT_gHmSu6&e7$aA;^XrpbhYh-p$sCiyN|J9NB8?Sg&zc&;bVP_9ZV4OLf#s>TH*`ZAvh;LX}Py*Sr?A5FWWnbjg?54o}X{{ z>&qHO{`E+UDWTD^<5>6&McgxC-3&VaY4cS;A{*QXvCksESoHJ~30DjLSUSJO`x(?J z!0s4APM#%~q)1J#&8V;x-4zv5>bV#H`7jl)t~l`nPF{aLo#5ML?rO97Z~{3X)wiT% zR%%R*^U5cvuZTogGF|C9-JG9PK<~uGfcZHF*q8e41Y&aHRN>Vm5Y%C?(cYQ?aqDz( zb){}r_5|O<_FFTv7X5bExtp1p$$N*RKzJ1rdUvnY@q584UnGtMTTljtXcrL9MCw(s zLlgF-Bn3F8*xMQGt){spM0;`HI7wx-o+BSABEe;7YF9=kq3H+Ay|d+3=2c(uh{AXZ72i`FG^ zu($F7`nd6;{ck5G{~&qzuJwK7>=0;zu?gc-kZ8q_jP3S%``#!v5WL_SoA2K$ z_$gj@4kMRV=0;0PDNEG3oJfb*?sGvHxn@%bU-o-OMvRm&@1$)k?BdAnWW5{t3 z^J7%CukYId6c83vkqbUSzvOyFJO*MQXBll!0)6#eyLSbc zU$+$#2{5;jXu);_plA8{Up%ZoUEA=9jRa?8?A0PAs7=jIUZ!-1 zcln-w3>hn$_H&H;xU+&H;40IUXG-$fnx&B@I2ky9`*+p`O6tQs9GwiyaI81w;cAz~ zMkJh184nFNhAYoZtYi*~fRf?recdtr?te#++7xvA*Zbi78E!P{kiNDx_p^lUxKs%a zNUi5x?Pc*O7Pbz~4bIcLHlp{IsMsuohc-?a)S#YMDjM}PX71|yF<|V zJX5*nFuD?5XC`1U4RuR&Kf}YURB^Z~|1&94pZ#*+$@h;&5leBG`CHETC>>d z!iJm7FzlZgjH7PewhPTB&YBx4m`5+z9`)fxCODpDsvR1eizQLp=k2Ss+4}qlV~jmf zn(4*-&I#K4^6D(GpHpqaOj`sh=iZ&SE>BQHRQvI+da<+(F%H^m@WBkzbShc_3b;fx zRk&V9?xmwXvdGtP3NdCnD~5I69zEo&&vfd`fD{`)#A(pt&p2J5h@+e#op`-0(BK=r z6q5s-h>JAiTuZt3!EMxU9~UNe&YPn9N+3D6YE)$pAcO!<mxq_Q|*vb;{%_AWVl zd_T*l&#L?$#`8S%BR=-`a<*_bYIMbBbM(~y#YB=$gU;F%b6ska&&gV4lKDSpR{7hn zvhdQV!lAUGKPe10Ag+SybP0laE@UX;mX!m+P^n>Bve{_B zKm06;t>q?!^U-J2f$st-%)bp~*lW#BKWKgjuPbQm7cw`OhgA-VncFBh&Y<(0?ccfo zPp6?HGCb$3XXN8`K}hH63Un)%^2uPZeL{d8)z=_c^s^-mu}-a3L`8RM*xU z4lec6>bukRD0#z_fYf$>EETjK5bFo=2NPFA2^P7yMEs1U&33V-4 zf2+XUnh(cRQ2l93e^u7%kKBGt)v1E-okd2YSZZH?Um8C#U8gUG` zV~sh6B-1ov9|k}BU-y;#p5d%l`^z+?PfYtq{RRLWl5*cJC#B0+F>P8%C49^Gv1P5}JEC-fMzmJ=Q+Jxbu>0 zUjG_dVW^G8t8tvh#Sq|!M}RNBLKpVXe^B>ZY9&H=V?0mdc39ye>-@voe7^mA5JYsf zTJerdE%C7qLiD9^LEw^b63e4}G+%+js2ZiHyAgq#o_;>;Lhm-iF5; z-UBY7RSjfd4eZ*tyP&XhL^cU}e<09r+A(ecVIO?U86{Qr5l?L<>BHPswU5KMyc;A`Ml%(aE>29n05 z!haMLD+*EwCPIcs&h4Ax+@$uI@-a@z<&Ox?0+^D#MfEbx+*t+C`7runyAC5{u%R1I z_sox9x?)czy?LfStZ;ki2ny(<3SM$nu1ha`3Ml52PVc>a-@9D2aXWc4!oEB9z@vCr zFyuH7!+cMge&Q*lSni&3qYKzr6hWV*UJmW z&L>XI(qQk6*^!REN%2QPW9;#?@y#z0(0#tLp6}n>CPu`4^RpF)G(`aJ;gL1fW5{N1 zntlC*k%6Y-+||zxp+IvwtSb+d7^@G9ghW`nU8koy6Q74Z2&`u>f3;|b8u2Px-4Qr$ z4lN|e!__kG=t~u?z|+v3k?{ra(yO}~;-qRGCl9~26ZX<=D3wtdw3((k($2ou=D$07T_ z_j$lE=l0pY^_bhZ{-6})nSSs98HJrx6;3F0)Wv`32ux{NoD1h0q{q{lq7uuzI#LVs z!R!QK-qRoq$3=`}2)4D8?u=KzHsDM4DG3XM8d)s~fL zWK{dhlmr<}a3S%{&&ulIlZyXQO^VubnoZQLYwqjGN~^MX85J7XZxSdX$~-GEWCX;! zw<(B9x1Yp5aK!S6x2{LpmI#Amm&<4$e5}@3Jjq{rS`Kl^MtfeNy2Y&CuSz$hM;WNvIBFKZv*xA7~OVUyW(< z6SBBj%IBYXAiuqKu;-zIdTz?Wzjj{m7>M#Kr~+UWO$nSJ zlS=@9T}1O09v zGU2>hc|jV+$K>1BQ{+r<4Q99K(S?03Lng|4dqu(H=|hioX1MU|tjQAzY>$zT4^; zm(sU6Tq*X8O=A{i;4#W>vXG(3zpsL~=U%)Lvv+2tyv(>|MZ5hU&ce;OgY(OuyofZquOUML&N zVOm~U$~XVDy%JOIm({tXvhb?eDq$k*nlazm4_BWNH18zhuY1fJoRgK!v$gBnKK-G4 z33}{3rYEPc+p6|XiLzfVJZnA?YRqLJVxvq_+(ddyR53tCNU=%D)H9mO3y*_1)s0K^ zZhN`jZ2gd3nE?#@o>AC9g_||0EN=hN`m+08)2cS6s$<{K{lJe837A_l@y$Awh^%yI z(yi(2g+;ogx%|cg-}UmcUK6gpev#0fpubkh>KTcpBL-4AeKcOrv(Oj(u+bj|Th<^0 zdK1UwhKdZiS{Zrmuf*q-)^Z81B@2`Cn*243D)y}hd5&=^DjnDTvqz=h3ybC*KJfp! zZT0?g%?Vgl!n~L;-(iZ6Cyf>Li8gx26g= z<{L!<)4_T<>cIqJ1dCeKBjC(i3_A7VPzmUk>s{iq6?Q&ZsQUGRiI69YYVvAV-7slV zsx^UK&&>ViJV!m1n_MBi4NG7&wnS8Cew)|WV(8AQDXZW(VcLf0{Q1vr?w@&J!r#`I z38{`Kb_J`SkOLDLvuO1%rfzO_LS0_rrjst|5X51Ru1s-6Q>5;fjPkTEwUkn0#U}mt zuaUpo+eMmhs)yU1*2l6t+@FKt*>v=n@9ZMS>@aHQH_T#Sj)p8%ti$Z>OP%w>i!!O) z?3N2bl~vChhETedjEW_GoOy&{Hf=Ns1p@y>G9yi`7QmQmRqM00`i>Q;8fdz{Ny~X($nU>tKs#9Cg*L1_zJ!IUPsx%co;G_LN_YQTf2gl?i9JR zak78fu*i#oN|w5KIpc4S3aIZMlZZ6qY5z_!ZDb4~eTq|rJ%9g6he*@b_QTFQvW zAK+9L9W74-Vv6<-52uTY*Y@{Faqj27^RxB$6$PPq_XL>@{mr!+XR`j1X$}80=+is= zQQ({+a?XumiOWAF&d|HC!wWsbi*Bj)iipb|qPCob6x1Y(+$L4LHds?j1vogvQjB#r z(|XDP1j2xIxSS$F|4>@VYnJ~--S%&C++mqP;;0rMWd~K5R zgyZhRa?9kfd758VE;MN;Z7jknDq&-eJdLj~b+Ay-k;?C9C9PEy5wb19#4gAzxVVl-S&*y6XqQX3;EL`n;z z4)_owdEny7Z%u#ycVSNUi`)ndvK%PI3)}a9{5?J|*D<`b8W*XtGM%sT6yfO(3PtZ* z--#SwPO2s+8~i=*&+zZlhL723(f+AOid%9MDG1uYAdW(f9JjWCZza)ngRIpaC^8{a zncotk5p!6TY4><{6h2s7@ihxHD{FkMm@QEpQ%qvREpEAmnD;Q`;#<9ti(1EG{(=in z1}bpRW1A>s$$#D7+;Xm+i{~xOOsaFB-o)9Ol=UD>1`1@X)L1xO?A1v~ylc_p#pfzN z{0|ijfk~+O4tX6J!sUy{6U;d#1+C8Cw*(&tn3%a-xr;ES<*sWoJAlaKnz_4bllkeA zUV9ltK!-u0yU5Z^>Nhm}hbpzxxC+<}#9@d=Od(eMrJpui3DeUv^NRiuE!Pj?U!4f} z1-TRexo4BNYT@L_e^UCXERDt!rHNBcoUo#+qa5)T{pep*WKdclIp=kPAyA-p0!I3B zqoW6WPEiaHCXFV!@mv4#KTbQdBC= zw0gmmrfu+T*e=(pdaFQGQiisi_-EIA{$3~dObcp|E(lbR-I_9Xv<@?!CFZ7EW)od7I-)m*joKDvAgwH# zI&{1(oHnu=Aj)!{`A1sab497JZ{G0 z81V9MyFa(X*XF3up@1I=pfKoxl^T~FyQ&I~p-{E5Xyy1~_(?`NG0_>ic}bKr?{pHA zar+|+!;|O!((Bo@1G;qnY*wlAFY(jQm-K)as!3(UaCl=SZDUK}s50%| z3?3Wn{*shr^dH?#tGn`q0Vn5Ow8~4V<-8~&FBOYKG&4zEl^=uyMN+70(m&wFX%|)H zQ`4B{XCpwDT9!g?PWMAD5=SfjGAxdf+17$YcpoSR{l0=_A%k{_PU`GSS8&aHJg`=> zc3&J&iw<8C?GW3lM|++^@1yAwECV}A%?_ss5HkRb51GYbpriTOY6`y9U0zOFQH5SlA`~6s<8|{t30UfY?%8 zQuS6(ek_YQ!EoL#^6x(r#;DOUf8!u$icMO`+m3mG<0`G-m*Ko1 zgOtH+F@i8OPq9|{^SWe*N;Qc}@s$*DNR5#RFUtcMNd-L9pP%V@9|10N&CS(&rX&4LmOIRo&=R%zlu}Z|E`>ONqH>~Eu{X!O0VG(+ z1s>K3)h1@A2&c-KV>;5y;y`RQgac7)76kDnajQW)P2+OSgI6pR@o@#-kA<+RGOEbQ zm{$6~%KXd49^?-b(f?Z0z?Dm~UJy8!#*`8Yf6W#`1Wy^xISUTg7pWcIIQLgeZ;2Dz z#rJxcs}--_`uL9*;2Q~Y@N@Ug%-|F z>@9>L{Bj{`WMpKydfm*{elvBJE#Ps}P}k599~;-lm?D1;#UZpr@4DF0rYU&UEion& zN-|7<#(eyU$t&QJOSXJ9Pma*!@}2TyL&-(;0KqswJ@TE%1JW?@Z6p*LQQHeQXll+1 zffNNl78B0Mb_J3>PnFG|`gbuy5sIgMnCO(+4j2DTS~}a8G-zhXq^VP5G1~L6u%N-8 z0Up@B{t_A*y8XF7Ud#ia55a59ABQ1XKx{U#Y^{MpPn z(NOfl+@4ZaVlYZ|u-YJ$6I&}wttN)qQ&d#=w4&C8&k!QJi4Y`e+fh?_-Z=0.8.0" - }, - "dependencies": { - "hoek": "2.x.x" - }, - "devDependencies": { - "code": "1.x.x", - "lab": "5.x.x" - }, - "scripts": { - "test": "lab -a code -t 100", - "test-cov-html": "lab -a code -r html -o coverage.html" - }, - "license": "BSD-3-Clause", - "gitHead": "29be188e9ecfce3a2e090b8714dec2b6e0791724", - "bugs": { - "url": "https://github.com/hapijs/boom/issues" - }, - "homepage": "https://github.com/hapijs/boom", - "_id": "boom@2.7.2", - "_shasum": "dad628d897f7fd2e32cc82197f13307971cf8354", - "_from": "boom@2.7.2", - "_npmVersion": "2.7.0", - "_nodeVersion": "0.10.38", - "_npmUser": { - "name": "arb", - "email": "arbretz@gmail.com" - }, - "maintainers": [ - { - "name": "hueniverse", - "email": "eran@hueniverse.com" - }, - { - "name": "wyatt", - "email": "wpreul@gmail.com" - }, - { - "name": "arb", - "email": "arbretz@gmail.com" - } - ], - "dist": { - "shasum": "dad628d897f7fd2e32cc82197f13307971cf8354", - "tarball": "http://registry.npmjs.org/boom/-/boom-2.7.2.tgz" - }, - "directories": {}, - "_resolved": "https://registry.npmjs.org/boom/-/boom-2.7.2.tgz", - "readme": "ERROR: No README data found!" -} diff --git a/node_modules/hapi/node_modules/boom/test/index.js b/node_modules/hapi/node_modules/boom/test/index.js deleted file mode 100755 index a0db4df..0000000 --- a/node_modules/hapi/node_modules/boom/test/index.js +++ /dev/null @@ -1,615 +0,0 @@ -// Load modules - -var Util = require('util'); -var Code = require('code'); -var Boom = require('../lib'); -var Lab = require('lab'); - - -// Declare internals - -var internals = {}; - - -// Test shortcuts - -var lab = exports.lab = Lab.script(); -var describe = lab.describe; -var it = lab.it; -var expect = Code.expect; - - -it('returns the same object when already boom', function (done) { - - var error = Boom.badRequest(); - var wrapped = Boom.wrap(error); - expect(error).to.equal(wrapped); - done(); -}); - -it('returns an error with info when constructed using another error', function (done) { - - var error = new Error('ka-boom'); - error.xyz = 123; - var err = Boom.wrap(error); - expect(err.xyz).to.equal(123); - expect(err.message).to.equal('ka-boom'); - expect(err.output).to.deep.equal({ - statusCode: 500, - payload: { - statusCode: 500, - error: 'Internal Server Error', - message: 'An internal server error occurred' - }, - headers: {} - }); - expect(err.data).to.equal(null); - done(); -}); - -it('does not override data when constructed using another error', function (done) { - - var error = new Error('ka-boom'); - error.data = { useful: 'data' }; - var err = Boom.wrap(error); - expect(err.data).to.equal(error.data); - done(); -}); - -it('sets new message when none exists', function (done) { - - var error = new Error(); - var wrapped = Boom.wrap(error, 400, 'something bad'); - expect(wrapped.message).to.equal('something bad'); - done(); -}); - -it('throws when statusCode is not a number', function (done) { - - expect(function () { - - Boom.create('x'); - }).to.throw('First argument must be a number (400+): x'); - done(); -}); - -it('will cast a number-string to an integer', function (done) { - - var codes = [ - { input: '404', result: 404 }, - { input: '404.1', result: 404 }, - { input: 400, result: 400 }, - { input: 400.123, result: 400 }] - for (var i = 0, il = codes.length; i < il; ++i) { - var code = codes[i]; - var err = Boom.create(code.input); - expect(err.output.statusCode).to.equal(code.result); - } - - done(); -}); - -it('throws when statusCode is not finite', function (done) { - - expect(function () { - - Boom.create(1 / 0); - }).to.throw('First argument must be a number (400+): null'); - done(); -}); - -it('sets error code to unknown', function (done) { - - var err = Boom.create(999); - expect(err.output.payload.error).to.equal('Unknown'); - done(); -}); - -describe('create()', function () { - - it('does not sets null message', function (done) { - - var error = Boom.unauthorized(null); - expect(error.output.payload.message).to.not.exist(); - expect(error.isServer).to.be.false(); - done(); - }); - - it('sets message and data', function (done) { - - var error = Boom.badRequest('Missing data', { type: 'user' }); - expect(error.data.type).to.equal('user'); - expect(error.output.payload.message).to.equal('Missing data'); - done(); - }); -}); - -describe('isBoom()', function () { - - it('returns true for Boom object', function (done) { - - expect(Boom.badRequest().isBoom).to.equal(true); - done(); - }); - - it('returns false for Error object', function (done) { - - expect((new Error()).isBoom).to.not.exist(); - done(); - }); -}); - -describe('badRequest()', function () { - - it('returns a 400 error statusCode', function (done) { - - var error = Boom.badRequest(); - - expect(error.output.statusCode).to.equal(400); - expect(error.isServer).to.be.false(); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.badRequest('my message').message).to.equal('my message'); - done(); - }); - - it('sets the message to HTTP status if none provided', function (done) { - - expect(Boom.badRequest().message).to.equal('Bad Request'); - done(); - }); -}); - -describe('unauthorized()', function () { - - it('returns a 401 error statusCode', function (done) { - - var err = Boom.unauthorized(); - expect(err.output.statusCode).to.equal(401); - expect(err.output.headers).to.deep.equal({}); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.unauthorized('my message').message).to.equal('my message'); - done(); - }); - - it('returns a WWW-Authenticate header when passed a scheme', function (done) { - - var err = Boom.unauthorized('boom', 'Test'); - expect(err.output.statusCode).to.equal(401); - expect(err.output.headers['WWW-Authenticate']).to.equal('Test error="boom"'); - done(); - }); - - it('returns a WWW-Authenticate header set to the schema array value', function (done) { - - var err = Boom.unauthorized(null, ['Test','one','two']); - expect(err.output.statusCode).to.equal(401); - expect(err.output.headers['WWW-Authenticate']).to.equal('Test, one, two'); - done(); - }); - - it('returns a WWW-Authenticate header when passed a scheme and attributes', function (done) { - - var err = Boom.unauthorized('boom', 'Test', { a: 1, b: 'something', c: null, d: 0 }); - expect(err.output.statusCode).to.equal(401); - expect(err.output.headers['WWW-Authenticate']).to.equal('Test a="1", b="something", c="", d="0", error="boom"'); - done(); - }); - - it('returns a WWW-Authenticate header when passed attributes, missing error', function (done) { - - var err = Boom.unauthorized(null, 'Test', { a: 1, b: 'something', c: null, d: 0 }); - expect(err.output.statusCode).to.equal(401); - expect(err.output.headers['WWW-Authenticate']).to.equal('Test a="1", b="something", c="", d="0"'); - expect(err.isMissing).to.equal(true); - done(); - }); - - it('sets the isMissing flag when error message is empty', function (done) { - - var err = Boom.unauthorized('', 'Basic'); - expect(err.isMissing).to.equal(true); - done(); - }); - - it('does not set the isMissing flag when error message is not empty', function (done) { - - var err = Boom.unauthorized('message', 'Basic'); - expect(err.isMissing).to.equal(undefined); - done(); - }); - - it('sets a WWW-Authenticate when passed as an array', function (done) { - - var err = Boom.unauthorized('message', ['Basic', 'Example e="1"', 'Another x="3", y="4"']); - expect(err.output.headers['WWW-Authenticate']).to.equal('Basic, Example e="1", Another x="3", y="4"'); - done(); - }); -}); - - -describe('methodNotAllowed()', function () { - - it('returns a 405 error statusCode', function (done) { - - expect(Boom.methodNotAllowed().output.statusCode).to.equal(405); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.methodNotAllowed('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('notAcceptable()', function () { - - it('returns a 406 error statusCode', function (done) { - - expect(Boom.notAcceptable().output.statusCode).to.equal(406); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.notAcceptable('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('proxyAuthRequired()', function () { - - it('returns a 407 error statusCode', function (done) { - - expect(Boom.proxyAuthRequired().output.statusCode).to.equal(407); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.proxyAuthRequired('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('clientTimeout()', function () { - - it('returns a 408 error statusCode', function (done) { - - expect(Boom.clientTimeout().output.statusCode).to.equal(408); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.clientTimeout('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('conflict()', function () { - - it('returns a 409 error statusCode', function (done) { - - expect(Boom.conflict().output.statusCode).to.equal(409); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.conflict('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('resourceGone()', function () { - - it('returns a 410 error statusCode', function (done) { - - expect(Boom.resourceGone().output.statusCode).to.equal(410); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.resourceGone('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('lengthRequired()', function () { - - it('returns a 411 error statusCode', function (done) { - - expect(Boom.lengthRequired().output.statusCode).to.equal(411); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.lengthRequired('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('preconditionFailed()', function () { - - it('returns a 412 error statusCode', function (done) { - - expect(Boom.preconditionFailed().output.statusCode).to.equal(412); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.preconditionFailed('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('entityTooLarge()', function () { - - it('returns a 413 error statusCode', function (done) { - - expect(Boom.entityTooLarge().output.statusCode).to.equal(413); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.entityTooLarge('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('uriTooLong()', function () { - - it('returns a 414 error statusCode', function (done) { - - expect(Boom.uriTooLong().output.statusCode).to.equal(414); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.uriTooLong('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('unsupportedMediaType()', function () { - - it('returns a 415 error statusCode', function (done) { - - expect(Boom.unsupportedMediaType().output.statusCode).to.equal(415); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.unsupportedMediaType('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('rangeNotSatisfiable()', function () { - - it('returns a 416 error statusCode', function (done) { - - expect(Boom.rangeNotSatisfiable().output.statusCode).to.equal(416); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.rangeNotSatisfiable('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('expectationFailed()', function () { - - it('returns a 417 error statusCode', function (done) { - - expect(Boom.expectationFailed().output.statusCode).to.equal(417); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.expectationFailed('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('badData()', function () { - - it('returns a 422 error statusCode', function (done) { - - expect(Boom.badData().output.statusCode).to.equal(422); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.badData('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('tooManyRequests()', function () { - - it('returns a 429 error statusCode', function (done) { - - expect(Boom.tooManyRequests().output.statusCode).to.equal(429); - done(); - }); - - it('sets the message with the passed-in message', function (done) { - - expect(Boom.tooManyRequests('my message').message).to.equal('my message'); - done(); - }); -}); - -describe('serverTimeout()', function () { - - it('returns a 503 error statusCode', function (done) { - - expect(Boom.serverTimeout().output.statusCode).to.equal(503); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.serverTimeout('my message').message).to.equal('my message'); - done(); - }); -}); - -describe('forbidden()', function () { - - it('returns a 403 error statusCode', function (done) { - - expect(Boom.forbidden().output.statusCode).to.equal(403); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.forbidden('my message').message).to.equal('my message'); - done(); - }); -}); - -describe('notFound()', function () { - - it('returns a 404 error statusCode', function (done) { - - expect(Boom.notFound().output.statusCode).to.equal(404); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.notFound('my message').message).to.equal('my message'); - done(); - }); -}); - -describe('internal()', function () { - - it('returns a 500 error statusCode', function (done) { - - expect(Boom.internal().output.statusCode).to.equal(500); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - var err = Boom.internal('my message'); - expect(err.message).to.equal('my message'); - expect(err.isServer).to.true(); - expect(err.output.payload.message).to.equal('An internal server error occurred'); - done(); - }); - - it('passes data on the callback if its passed in', function (done) { - - expect(Boom.internal('my message', { my: 'data' }).data.my).to.equal('data'); - done(); - }); - - it('returns an error with composite message', function (done) { - - try { - JSON.parse('{'); - } - catch (err) { - var boom = Boom.internal('Someting bad', err); - expect(boom.message).to.equal('Someting bad: Unexpected end of input'); - expect(boom.isServer).to.be.true(); - done(); - } - }); -}); - -describe('notImplemented()', function () { - - it('returns a 501 error statusCode', function (done) { - - expect(Boom.notImplemented().output.statusCode).to.equal(501); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.notImplemented('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('badGateway()', function () { - - it('returns a 502 error statusCode', function (done) { - - expect(Boom.badGateway().output.statusCode).to.equal(502); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.badGateway('my message').message).to.equal('my message'); - done(); - }); -}); - -describe('gatewayTimeout()', function () { - - it('returns a 504 error statusCode', function (done) { - - expect(Boom.gatewayTimeout().output.statusCode).to.equal(504); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.gatewayTimeout('my message').message).to.equal('my message'); - done(); - }); -}); - -describe('badImplementation()', function () { - - it('returns a 500 error statusCode', function (done) { - - var err = Boom.badImplementation(); - expect(err.output.statusCode).to.equal(500); - expect(err.isDeveloperError).to.equal(true); - expect(err.isServer).to.be.true(); - done(); - }); -}); diff --git a/node_modules/hapi/node_modules/catbox/.npmignore b/node_modules/hapi/node_modules/catbox/.npmignore deleted file mode 100644 index 77ba16c..0000000 --- a/node_modules/hapi/node_modules/catbox/.npmignore +++ /dev/null @@ -1,18 +0,0 @@ -.idea -*.iml -npm-debug.log -dump.rdb -node_modules -results.tap -results.xml -npm-shrinkwrap.json -config.json -.DS_Store -*/.DS_Store -*/*/.DS_Store -._* -*/._* -*/*/._* -coverage.* -lib-cov - diff --git a/node_modules/hapi/node_modules/catbox/.travis.yml b/node_modules/hapi/node_modules/catbox/.travis.yml deleted file mode 100755 index f502178..0000000 --- a/node_modules/hapi/node_modules/catbox/.travis.yml +++ /dev/null @@ -1,6 +0,0 @@ -language: node_js - -node_js: - - 0.10 - - 0.12 - - iojs diff --git a/node_modules/hapi/node_modules/catbox/LICENSE b/node_modules/hapi/node_modules/catbox/LICENSE deleted file mode 100755 index 4a87d4e..0000000 --- a/node_modules/hapi/node_modules/catbox/LICENSE +++ /dev/null @@ -1,28 +0,0 @@ -Copyright (c) 2012-2014, Walmart and other contributors. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The names of any contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - * * * - -The complete list of contributors can be found at: https://github.com/hapijs/catbox/graphs/contributors \ No newline at end of file diff --git a/node_modules/hapi/node_modules/catbox/Makefile b/node_modules/hapi/node_modules/catbox/Makefile deleted file mode 100755 index 5404b23..0000000 --- a/node_modules/hapi/node_modules/catbox/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -test: - @node node_modules/lab/bin/lab -test-cov: - @node node_modules/lab/bin/lab -t 100 -test-cov-html: - @node node_modules/lab/bin/lab -r html -o coverage.html - -.PHONY: test test-cov test-cov-html - diff --git a/node_modules/hapi/node_modules/catbox/README.md b/node_modules/hapi/node_modules/catbox/README.md deleted file mode 100755 index a7aa95e..0000000 --- a/node_modules/hapi/node_modules/catbox/README.md +++ /dev/null @@ -1,136 +0,0 @@ -![catbox Logo](https://raw.github.com/hapijs/catbox/master/images/catbox.png) - -Multi-strategy object caching service -Version: **4.x** - -[![Build Status](https://secure.travis-ci.org/hapijs/catbox.png)](http://travis-ci.org/hapijs/catbox) - -Lead Maintainer: [Ben Acker](https://github.com/nvcexploder) - -**catbox** is a multi-strategy key-value object store. It comes with extensions supporting a memory cache, -[Redis](http://redis.io/), [MongoDB](http://www.mongodb.org/), [Memcached](http://memcached.org/), [Riak](http://basho.com/riak/), [Amazon S3](http://aws.amazon.com/s3/), and [RethinkDB](http://rethinkdb.com). -**catbox** provides two interfaces: a low-level `Client` and a high-level `Policy`. - - -### Installation - -In order to reduce module dependencies, **catbox** does not includes the external caching strategies. To use other strategies, -each service must be manually installed via npm or package dependencies manually. The available strategies are: - -- [Memory](https://github.com/hapijs/catbox-memory) -- [Redis](https://github.com/hapijs/catbox-redis) -- [MongoDB](https://github.com/hapijs/catbox-mongodb) -- [Memcached](https://github.com/hapijs/catbox-memcached) -- [Riak](https://github.com/DanielBarnes/catbox-riak) -- [Amazon S3](https://github.com/fhemberger/catbox-s3) -- [RethinkDB](https://github.com/codedmart/catbox-rethinkdb) - - -### `Client` - -The `Client` object provides a low-level cache abstraction. The object is constructed using `new Client(engine, options)` where: - -- `engine` - is an object or a prototype function implementing the cache strategy: - - function - a prototype function with the signature `function(options)`. **catbox** will call `new func(options)`. - - object - a pre instantiated client implementation object. Does not support passing `options`. -- `options` - the strategy configuration object. Each strategy defines its own configuration options with the following common options: - - `partition` - the partition name used to isolate the cached results across multiple clients. The partition name is used - as the MongoDB database name, the Riak bucket, or as a key prefix in Redis and Memcached. To share the cache across multiple clients, - use the same partition name. - -Note that any implementation of client strategies must return deep copies of the stored data as the API assumes that the object returned -from a `get()` is owned by the called and can be safely modified without affecting the cache copy. - - -#### API - -The `Client` object provides the following methods: - -- `start(callback)` - creates a connection to the cache server. Must be called before any other method is available. - The `callback` signature is `function(err)`. -- `stop()` - terminates the connection to the cache server. -- `get(key, callback)` - retrieve an item from the cache engine if found where: - - `key` - a cache key object (see below). - - `callback` - a function with the signature `function(err, cached)`. If the item is not found, both `err` and `cached` are `null`. - If found, the `cached` object contains the following: - - `item` - the value stored in the cache using `set()`. - - `stored` - the timestamp when the item was stored in the cache (in milliseconds). - - `ttl` - the remaining time-to-live (not the original value used when storing the object). -- `set(key, value, ttl, callback)` - store an item in the cache for a specified length of time, where: - - `key` - a cache key object (see below). - - `value` - the string or object value to be stored. - - `ttl` - a time-to-live value in milliseconds after which the item is automatically removed from the cache (or is marked invalid). - - `callback` - a function with the signature `function(err)`. -- `drop(key, callback)` - remove an item from cache where: - - `key` - a cache key object (see below). - - `callback` - a function with the signature `function(err)`. - -Any method with a `key` argument takes an object with the following required properties: -- `segment` - a caching segment name string. Enables using a single cache server for storing different sets of items with overlapping ids. -- `id` - a unique item identifier string (per segment). Can be an empty string. - - -### `Policy` - -The `Policy` object provides a convenient cache interface by setting a global policy which is automatically applied to every storage action. -The object is constructed using `new Policy(options, [cache, segment])` where: - -- `options` - is an object with the following keys: - - `expiresIn` - relative expiration expressed in the number of milliseconds since the item was saved in the cache. Cannot be used - together with `expiresAt`. - - `expiresAt` - time of day expressed in 24h notation using the 'HH:MM' format, at which point all cache records for the route - expire. Uses local time. Cannot be used together with `expiresIn`. - - `generateFunc` - a function used to generate a new cache item if one is not found in the cache when calling `get()`. The method's - signature is `function(id, next)` where: - - `id` - the `id` string or object provided to the `get()` method. - - `next` - the method called when the new item is returned with the signature `function(err, value, ttl)` where: - - `err` - an error condition. - - `value` - the new value generated. - - `ttl` - the cache ttl value in milliseconds. Set to `0` to skip storing in the cache. Defaults to the cache global policy. - - `staleIn` - number of milliseconds to mark an item stored in cache as stale and attempt to regenerate it when `generateFunc` is - provided. Must be less than `expiresIn`. Alternatively function that returns staleIn value in miliseconds. The function signature is - `function(stored, ttl)` where: - - `stored` - the timestamp when the item was stored in the cache (in milliseconds). - - `ttl` - the remaining time-to-live (not the original value used when storing the object). - - `staleTimeout` - number of milliseconds to wait before checking if an item is stale. - - `generateTimeout` - number of milliseconds to wait before returning a timeout error when the `generateFunc` function - takes too long to return a value. When the value is eventually returned, it is stored in the cache for future requests. - - `dropOnError` - if `true`, an error or timeout in the `generateFunc` causes the stale value to be evicted from the cache. - Defaults to `true`. -- `cache` - a `Client` instance (which has already been started). -- `segment` - required when `cache` is provided. The segment name used to isolate cached items within the cache partition. - - -#### API - -The `Policy` object provides the following methods: - -- `get(id, callback)` - retrieve an item from the cache. If the item is not found and the `generateFunc` method was provided, a new value - is generated, stored in the cache, and returned. Multiple concurrent requests are queued and processed once. The method arguments are: - - `id` - the unique item identifier (within the policy segment). Can be a string or an object with the required 'id' key. - - `callback` - the return function. The function signature is `function(err, value, cached, report)` where: - - `err` - any errors encountered. - - `value` - the fetched or generated value. - - `cached` - `null` if a valid item was not found in the cache, or an object with the following keys: - - `item` - the cached `value`. - - `stored` - the timestamp when the item was stored in the cache. - - `ttl` - the cache ttl value for the record. - - `isStale` - `true` if the item is stale. - - `report` - an object with logging information about the generation operation containing the following keys (as relevant): - - `msec` - the cache lookup time in milliseconds. - - `stored` - the timestamp when the item was stored in the cache. - - `isStale` - `true` if the item is stale. - - `ttl` - the cache ttl value for the record. - - `error` - lookup error. -- `set(id, value, ttl, callback)` - store an item in the cache where: - - `id` - the unique item identifier (within the policy segment). - - `value` - the string or object value to be stored. - - `ttl` - a time-to-live **override** value in milliseconds after which the item is automatically removed from the cache (or is marked invalid). - This should be set to `0` in order to use the caching rules configured when creating the `Policy` object. - - `callback` - a function with the signature `function(err)`. -- `drop(id, callback)` - remove the item from cache where: - - `id` - the unique item identifier (within the policy segment). - - `callback` - a function with the signature `function(err)`. -- `ttl(created)` - given a `created` timestamp in milliseconds, returns the time-to-live left based on the configured rules. -- `rules(options) - changes the policy rules after construction (note that items already stored will not be affected) where: - - `options` - the same `options` as the `Policy` constructor. diff --git a/node_modules/hapi/node_modules/catbox/examples/policy.js b/node_modules/hapi/node_modules/catbox/examples/policy.js deleted file mode 100755 index 7f0adfb..0000000 --- a/node_modules/hapi/node_modules/catbox/examples/policy.js +++ /dev/null @@ -1,64 +0,0 @@ -// After starting this example load http://localhost:8080 and hit refresh, you will notice that it loads the response from cache for the first 5 seconds and then reloads the cache. Look at the console to see it setting and getting items from cache. - -// Load modules - -var Catbox = require('../'); -var Http = require('http'); - - - -// Declare internals - -var internals = {}; - - -internals.handler = function (req, res) { - - internals.getResponse(function (item) { - - res.writeHead(200, {'Content-Type': 'text/plain'}); - res.end(item); - }); -}; - - -internals.getResponse = function (callback) { - - internals.policy.get('myExample', callback); -}; - - -internals.startCache = function (callback) { - - var clientOptions = { - partition: 'examples' // For redis this will store items under keys that start with examples: - }; - - var policyOptions = { - expiresIn: 5000, - generateFunc: function (id, next) { - - var item = 'example'; - console.log(item); - return next(null, item); - } - }; - - var client = new Catbox.Client(require('../test/import'), clientOptions); - client.start(function () { - - internals.policy = new Catbox.Policy(policyOptions, client, 'example'); - callback(); - }); -}; - - -internals.startServer = function () { - - var server = Http.createServer(internals.handler); - server.listen(8080); - console.log('Server started at http://localhost:8080/'); -}; - - -internals.startCache(internals.startServer); \ No newline at end of file diff --git a/node_modules/hapi/node_modules/catbox/images/catbox.png b/node_modules/hapi/node_modules/catbox/images/catbox.png deleted file mode 100755 index cc1799f7e75fa901b506dcb5d1e18e15d8be889a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48752 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.10.32" - }, - "dependencies": { - "boom": "2.x.x", - "hoek": "2.x.x", - "joi": "6.x.x" - }, - "devDependencies": { - "code": "1.x.x", - "lab": "5.x.x" - }, - "scripts": { - "test": "make test-cov" - }, - "licenses": [ - { - "type": "BSD", - "url": "http://github.com/hapijs/catbox/raw/master/LICENSE" - } - ], - "gitHead": "597c1c5450f72730a2571d8cae6a0960b62ad8d2", - "bugs": { - "url": "https://github.com/hapijs/catbox/issues" - }, - "homepage": "https://github.com/hapijs/catbox", - "_id": "catbox@4.2.2", - "_shasum": "c29aeb384338f9b6de107849969bb76cab77eab4", - "_from": "catbox@4.2.2", - "_npmVersion": "2.5.1", - "_nodeVersion": "0.12.0", - "_npmUser": { - "name": "hueniverse", - "email": "eran@hueniverse.com" - }, - "maintainers": [ - { - "name": "hueniverse", - "email": "eran@hueniverse.com" - }, - { - "name": "wyatt", - "email": "wpreul@gmail.com" - } - ], - "dist": { - "shasum": "c29aeb384338f9b6de107849969bb76cab77eab4", - "tarball": "http://registry.npmjs.org/catbox/-/catbox-4.2.2.tgz" - }, - "directories": {}, - "_resolved": "https://registry.npmjs.org/catbox/-/catbox-4.2.2.tgz", - "readme": "ERROR: No README data found!" -} diff --git a/node_modules/hapi/node_modules/catbox/test/client.js b/node_modules/hapi/node_modules/catbox/test/client.js deleted file mode 100755 index d6c93b0..0000000 --- a/node_modules/hapi/node_modules/catbox/test/client.js +++ /dev/null @@ -1,393 +0,0 @@ -// Load modules - -var Catbox = require('..'); -var Code = require('code'); -var Lab = require('lab'); - - -// Declare internals - -var internals = {}; - - -// Test shortcuts - -var lab = exports.lab = Lab.script(); -var describe = lab.experiment; -var it = lab.test; -var expect = Code.expect; - - -describe('Client', function () { - - it('uses prototype engine', function (done) { - - var Obj = require('./import'); - var client = new Catbox.Client(Obj); - client.start(function (err) { - - expect(err).to.not.exist(); - - var key = { id: 'x', segment: 'test' }; - client.set(key, '123', 1000, function (err) { - - expect(err).to.not.exist(); - - client.get(key, function (err, result) { - - expect(err).to.not.exist(); - expect(result.item).to.equal('123'); - done(); - }); - }); - }); - }); - - it('supports empty keys', function (done) { - - var Obj = require('./import'); - var client = new Catbox.Client(Obj); - client.start(function (err) { - - expect(err).to.not.exist(); - - var key = { id: '', segment: 'test' }; - client.set(key, '123', 1000, function (err) { - - expect(err).to.not.exist(); - - client.get(key, function (err, result) { - - expect(err).to.not.exist(); - expect(result.item).to.equal('123'); - done(); - }); - }); - }); - }); - - it('uses object instance engine', function (done) { - - var Obj = require('./import'); - var client = new Catbox.Client(new Obj()); - client.start(function (err) { - - expect(err).to.not.exist(); - - var key = { id: 'x', segment: 'test' }; - client.set(key, '123', 1000, function (err) { - - expect(err).to.not.exist(); - - client.get(key, function (err, result) { - - expect(err).to.not.exist(); - expect(result.item).to.equal('123'); - done(); - }); - }); - }); - }); - - it('errors when calling get on a bad connection', function (done) { - - var errorEngine = { - start: function (callback) { callback(null); }, - stop: function () { }, - isReady: function () { return true; }, - validateSegmentName: function () { return null; }, - get: function (key, callback) { return callback(new Error('fail')); }, - set: function (key, value, ttl, callback) { return callback(new Error('fail')); }, - drop: function (key, callback) { return callback(new Error('fail')); } - }; - - var client = new Catbox.Client(errorEngine); - var key = { id: 'x', segment: 'test' }; - client.get(key, function (err, result) { - - expect(err).to.exist(); - expect(err.message).to.equal('fail'); - done(); - }); - }); - - describe('start()', function () { - - it('passes an error in the callback when one occurs', function (done) { - - var engine = { - start: function (callback) { - - callback(new Error()); - } - }; - - var client = new Catbox.Client(engine); - client.start(function (err) { - - expect(err).to.exist(); - done(); - }); - }); - }); - - describe('get()', function () { - - it('returns an error when the connection is not ready', function (done) { - - var engine = { - start: function (callback) { - - callback(); - }, - isReady: function () { - - return false; - } - }; - - var client = new Catbox.Client(engine); - client.get('test', function (err) { - - expect(err).to.be.instanceOf(Error); - expect(err.message).to.equal('Disconnected'); - done(); - }); - }); - - it('wraps the result with cached details', function (done) { - - var engine = { - start: function (callback) { - - callback(); - }, - isReady: function () { - - return true; - }, - get: function (key, callback) { - - var result = { - item: 'test1', - stored: 'test2' - }; - - callback(null, result); - } - }; - - var client = new Catbox.Client(engine); - client.get({ id: 'id', segment: 'segment' }, function (err, cached) { - - expect(cached.item).to.equal('test1'); - expect(cached.stored).to.equal('test2'); - expect(cached.ttl).to.exist(); - done(); - }); - }); - - it('returns nothing when item is not found', function (done) { - - var engine = { - start: function (callback) { - - callback(); - }, - isReady: function () { - - return true; - }, - get: function (key, callback) { - - callback(null, null); - } - }; - - var client = new Catbox.Client(engine); - client.get({ id: 'id', segment: 'segment' }, function (err, cached) { - - expect(err).to.equal(null); - expect(cached).to.equal(null); - done(); - }); - }); - - it('returns nothing when item is not found (undefined item)', function (done) { - - var engine = { - start: function (callback) { - - callback(); - }, - isReady: function () { - - return true; - }, - get: function (key, callback) { - - callback(null, { item: undefined }); - } - }; - - var client = new Catbox.Client(engine); - client.get({ id: 'id', segment: 'segment' }, function (err, cached) { - - expect(err).to.equal(null); - expect(cached).to.equal(null); - done(); - }); - }); - - it('returns falsey items', function (done) { - - var engine = { - start: function (callback) { - - callback(); - }, - isReady: function () { - - return true; - }, - get: function (key, callback) { - - callback(null, { - item: false, - stored: false - }); - } - }; - - var client = new Catbox.Client(engine); - client.get({ id: 'id', segment: 'segment' }, function (err, cached) { - - expect(err).to.equal(null); - expect(cached.item).to.equal(false); - done(); - }); - }); - - it('expires item', function (done) { - - var engine = { - start: function (callback) { - - callback(); - }, - isReady: function () { - - return true; - }, - get: function (key, callback) { - - var result = { - item: 'test1', - stored: Date.now() - 100, - ttl: 50 - }; - - callback(null, result); - } - }; - - var client = new Catbox.Client(engine); - client.get({ id: 'id', segment: 'segment' }, function (err, cached) { - - expect(err).to.equal(null); - expect(cached).to.equal(null); - done(); - }); - }); - - it('errors on empty key', function (done) { - - var client = new Catbox.Client(require('../test/import')); - client.start(function (err) { - - expect(err).to.not.exist(); - - client.get({}, function (err) { - - expect(err).to.exist(); - expect(err.message).to.equal('Invalid key'); - done(); - }); - }); - }); - }); - - describe('set()', function () { - - it('returns an error when the connection is not ready', function (done) { - - var engine = { - start: function (callback) { - - callback(); - }, - isReady: function () { - - return false; - } - }; - - var client = new Catbox.Client(engine); - client.set('test', 'test', 'test', function (err) { - - expect(err).to.be.instanceOf(Error); - expect(err.message).to.equal('Disconnected'); - done(); - }); - }); - }); - - describe('drop()', function () { - - it('calls the extension clients drop function', function (done) { - - var engine = { - start: function (callback) { - - callback(); - }, - isReady: function () { - - return true; - }, - drop: function (key, callback) { - - callback(null, 'success'); - } - }; - - var client = new Catbox.Client(engine); - client.drop({ id: 'id', segment: 'segment' }, function (err, result) { - - expect(result).to.equal('success'); - done(); - }); - }); - }); - - describe('validateKey()', function () { - - it('errors on missing segment', function (done) { - - var Obj = require('./import'); - var client = new Catbox.Client(Obj); - client.start(function (err) { - - expect(err).to.not.exist(); - - var key = { id: 'x' }; - client.set(key, '123', 1000, function (err) { - - expect(err).to.exist(); - expect(err.message).to.equal('Invalid key'); - done(); - }); - }); - }); - }); -}); diff --git a/node_modules/hapi/node_modules/catbox/test/policy.js b/node_modules/hapi/node_modules/catbox/test/policy.js deleted file mode 100755 index 306d287..0000000 --- a/node_modules/hapi/node_modules/catbox/test/policy.js +++ /dev/null @@ -1,1861 +0,0 @@ -// Load modules - -var Catbox = require('..'); -var Code = require('code'); -var Lab = require('lab'); -var Import = require('./import'); - - -// Declare internals - -var internals = {}; - - -// Test shortcuts - -var lab = exports.lab = Lab.script(); -var describe = lab.experiment; -var it = lab.test; -var expect = Code.expect; - - -describe('Policy', function () { - - it('returns cached item', function (done) { - - var client = new Catbox.Client(Import); - var policy = new Catbox.Policy({ expiresIn: 1000 }, client, 'test'); - - client.start(function (err) { - - expect(err).to.not.exist(); - - policy.set('x', '123', null, function (err) { - - expect(err).to.not.exist(); - - policy.get('x', function (err, value, cached, report) { - - expect(err).to.not.exist(); - expect(value).to.equal('123'); - done(); - }); - }); - }); - }); - - it('works with special property names', function (done) { - - var client = new Catbox.Client(Import); - var policy = new Catbox.Policy({ expiresIn: 1000 }, client, 'test'); - - client.start(function (err) { - - expect(err).to.not.exist(); - - policy.set('__proto__', '123', null, function (err) { - - expect(err).to.not.exist(); - - policy.get('__proto__', function (err, value, cached, report) { - - expect(err).to.not.exist(); - expect(value).to.equal('123'); - done(); - }); - }); - }); - }); - - it('finds nothing when using empty policy rules', function (done) { - - var client = new Catbox.Client(Import); - var policy = new Catbox.Policy({}, client, 'test'); - - client.start(function (err) { - - expect(err).to.not.exist(); - - policy.set('x', '123', null, function (err) { - expect(err).to.not.exist(); - - policy.get('x', function (err, value, cached, report) { - - expect(err).to.not.exist(); - expect(value).to.not.exist(); - done(); - }); - }); - }); - }); - - it('returns cached item with no global rules and manual ttl', function (done) { - - var client = new Catbox.Client(Import); - var policy = new Catbox.Policy({}, client, 'test'); - - client.start(function (err) { - - expect(err).to.not.exist(); - - policy.set('x', '123', 1000, function (err) { - expect(err).to.not.exist(); - - policy.get('x', function (err, value, cached, report) { - - expect(err).to.not.exist(); - expect(value).to.equal('123'); - done(); - }); - }); - }); - }); - - it('returns null on get when no cache client provided', function (done) { - - var policy = new Catbox.Policy({ expiresIn: 1 }); - - policy.get('x', function (err, value, cached, report) { - - expect(err).to.not.exist(); - expect(value).to.not.exist(); - done(); - }); - }); - - it('returns null on set when no cache client provided', function (done) { - - var policy = new Catbox.Policy({ expiresIn: 1 }); - - policy.set('x', 'y', 100, function (err) { - - expect(err).to.not.exist(); - done(); - }); - }); - - it('returns null on drop when no cache client provided', function (done) { - - var policy = new Catbox.Policy({ expiresIn: 1 }); - - policy.drop('x', function (err) { - - expect(err).to.not.exist(); - done(); - }); - }); - - it('returns null on get when item expired', function (done) { - - var client = new Catbox.Client(Import); - client.start(function () { - - var key = { id: 'x', segment: 'test' }; - client.set(key, 'y', 1, function (err) { - - setTimeout(function () { - - client.get(key, function (err, value, cached, report) { - - expect(err).to.not.exist(); - expect(value).to.not.exist(); - done(); - }); - }, 2); - }); - }); - }); - - it('throws an error when segment is missing', function (done) { - - var config = { - expiresIn: 50000 - }; - - var fn = function () { - - var client = new Catbox.Client(Import); - var policy = new Catbox.Policy(config, client); - }; - - expect(fn).to.throw('Invalid segment name: undefined (Empty string)'); - done(); - }); - - describe('get()', function () { - - it('returns cached item using object id', function (done) { - - var client = new Catbox.Client(Import); - var policy = new Catbox.Policy({ expiresIn: 1000 }, client, 'test'); - - client.start(function (err) { - - expect(err).to.not.exist(); - - policy.set({ id: 'x' }, '123', null, function (err) { - - expect(err).to.not.exist(); - - policy.get({ id: 'x' }, function (err, value, cached, report) { - - expect(err).to.not.exist(); - expect(value).to.equal('123'); - done(); - }); - }); - }); - }); - - it('returns error on null id', function (done) { - - var client = new Catbox.Client(Import); - var policy = new Catbox.Policy({ expiresIn: 1000 }, client, 'test'); - - client.start(function (err) { - - expect(err).to.not.exist(); - - policy.set(null, '123', null, function (err) { - - expect(err).to.exist(); - expect(err.message).to.equal('Invalid key'); - - policy.get(null, function (err, value, cached, report) { - - expect(err).to.exist(); - expect(err.message).to.equal('Invalid key'); - done(); - }); - }); - }); - }); - - it('passes an error to the callback when an error occurs getting the item', function (done) { - - var engine = { - start: function (callback) { - - callback(); - }, - isReady: function () { - - return true; - }, - get: function (key, callback) { - - callback(new Error()); - }, - validateSegmentName: function () { - - return null; - } - }; - var policyConfig = { - expiresIn: 50000 - }; - - var client = new Catbox.Client(engine); - var policy = new Catbox.Policy(policyConfig, client, 'test'); - - policy.get('test1', function (err, value, cached, report) { - - expect(err).to.be.instanceOf(Error); - expect(value).to.not.exist(); - done(); - }); - }); - - it('returns the cached result when no error occurs', function (done) { - - var engine = { - start: function (callback) { - - callback(); - }, - isReady: function () { - - return true; - }, - get: function (key, callback) { - - callback(null, { - stored: 'stored', - item: 'item' - }); - }, - validateSegmentName: function () { - - return null; - } - }; - var policyConfig = { - expiresIn: 50000 - }; - - var client = new Catbox.Client(engine); - var policy = new Catbox.Policy(policyConfig, client, 'test'); - - policy.get('test1', function (err, value, cached, report) { - - expect(value).to.equal('item'); - expect(cached.isStale).to.be.false; - done(); - }); - }); - - describe('generate', function () { - - it('returns falsey items', function (done) { - - var engine = { - start: function (callback) { - - callback(); - }, - isReady: function () { - - return true; - }, - get: function (key, callback) { - - callback(null, { - stored: false, - item: false - }); - }, - validateSegmentName: function () { - - return null; - } - }; - var policyConfig = { - expiresIn: 50000, - generateFunc: function (id, next) { - - return next(null, false); - } - }; - - var client = new Catbox.Client(engine); - var policy = new Catbox.Policy(policyConfig, client, 'test'); - - policy.get('test1', function (err, value, cached, report) { - - expect(err).to.equal(null); - expect(value).to.equal(false); - done(); - }); - }); - - it('bypasses cache when not configured', function (done) { - - var policy = new Catbox.Policy({ - expiresIn: 1, - generateFunc: function (id, next) { - - return next(null, 'new result'); - } - }); - - policy.get('test', function (err, value, cached, report) { - - expect(err).to.not.exist(); - expect(value).to.equal('new result'); - expect(cached).to.not.exist(); - done(); - }); - }); - - it('returns the processed cached item', function (done) { - - var rule = { - expiresIn: 100, - staleIn: 20, - staleTimeout: 5, - generateFunc: function (id, next) { - - return next(null, { gen: ++gen }); - } - }; - - var client = new Catbox.Client(Import, { partition: 'test-partition' }); - var policy = new Catbox.Policy(rule, client, 'test-segment'); - - var gen = 0; - - client.start(function () { - - policy.get('test', function (err, value, cached, report) { - - expect(value.gen).to.equal(1); - done(); - }); - }); - }); - - it('switches rules after construction', function (done) { - - var rule = { - expiresIn: 100, - staleIn: 20, - staleTimeout: 5, - generateFunc: function (id, next) { - - return next(null, { gen: ++gen }); - } - }; - - var client = new Catbox.Client(Import, { partition: 'test-partition' }); - var policy = new Catbox.Policy({ expiresIn: 100 }, client, 'test-segment'); - - var gen = 0; - - client.start(function () { - - policy.get('test', function (err, value, cached, report) { - - expect(value).to.not.exist(); - policy.rules(rule); - - policy.get('test', function (err, value, cached, report) { - - expect(value.gen).to.equal(1); - done(); - }); - }); - }); - }); - - it('returns the processed cached item after cache error', function (done) { - - var rule = { - expiresIn: 100, - staleIn: 20, - staleTimeout: 5, - generateFunc: function (id, next) { - - return next(null, { gen: ++gen }); - } - }; - - var client = new Catbox.Client(Import, { partition: 'test-partition' }); - client.get = function (key, callback) { callback(new Error('bad client')); }; - var policy = new Catbox.Policy(rule, client, 'test-segment'); - - var gen = 0; - - client.start(function () { - - policy.get('test', function (err, value, cached, report) { - - expect(value.gen).to.equal(1); - done(); - }); - }); - }); - - it('returns the processed cached item using manual ttl', function (done) { - - var rule = { - expiresIn: 26, - staleIn: 20, - staleTimeout: 5, - generateFunc: function (id, next) { - - setTimeout(function () { - - return next(null, { gen: ++gen }, 100); - }, 6); - } - }; - - var client = new Catbox.Client(Import, { partition: 'test-partition' }); - var policy = new Catbox.Policy(rule, client, 'test-segment'); - - var gen = 0; - - client.start(function () { - - policy.get('test', function (err, value1, cached, report) { - - expect(value1.gen).to.equal(1); // Fresh - setTimeout(function () { - - policy.get('test', function (err, value2, cached, report) { - - expect(value2.gen).to.equal(1); // Stale - done(); - }); - }, 27); - }); - }); - }); - - it('returns stale object then fresh object based on timing', function (done) { - - var rule = { - expiresIn: 100, - staleIn: 20, - staleTimeout: 5, - generateFunc: function (id, next) { - - setTimeout(function () { - - return next(null, { gen: ++gen }, 100); - }, 6); - } - }; - - var client = new Catbox.Client(Import, { partition: 'test-partition' }); - var policy = new Catbox.Policy(rule, client, 'test-segment'); - - var gen = 0; - - client.start(function () { - - policy.get('test', function (err, value1, cached, report) { - - expect(value1.gen).to.equal(1); // Fresh - setTimeout(function () { - - policy.get('test', function (err, value2, cached, report) { - - expect(value2.gen).to.equal(1); // Stale - setTimeout(function () { - - policy.get('test', function (err, value3, cached, report) { - - expect(value3.gen).to.equal(2); // Fresh - done(); - }); - }, 3); - }); - }, 21); - }); - }); - }); - - it('returns stale object then fresh object based on timing using staleIn function', function (done) { - - var staleIn = function (stored, ttl) { - - var expiresIn = (Date.now() - stored) + ttl; - expect(expiresIn).to.be.about(100, 5); - return expiresIn - 80; - }; - - var rule = { - expiresIn: 100, - staleIn: staleIn, - staleTimeout: 5, - generateFunc: function (id, next) { - - setTimeout(function () { - - return next(null, { gen: ++gen }, 100); - }, 6); - } - }; - - var client = new Catbox.Client(Import, { partition: 'test-partition' }); - var policy = new Catbox.Policy(rule, client, 'test-segment'); - - var gen = 0; - - client.start(function () { - - policy.get('test', function (err, value1, cached, report) { - - expect(value1.gen).to.equal(1); // Fresh - setTimeout(function () { - - policy.get('test', function (err, value2, cached, report) { - - expect(value2.gen).to.equal(1); // Stale - setTimeout(function () { - - policy.get('test', function (err, value3, cached, report) { - - expect(value3.gen).to.equal(2); // Fresh - done(); - }); - }, 3); - }); - }, 21); - }); - }); - }); - - it('returns stale object then invalidate cache on error', function (done) { - - var rule = { - expiresIn: 100, - staleIn: 20, - staleTimeout: 5, - generateFunc: function (id, next) { - - ++gen; - - setTimeout(function () { - - if (gen !== 2) { - return next(null, { gen: gen }); - } - - return next(new Error()); - }, 6); - } - }; - - var client = new Catbox.Client(Import, { partition: 'test-partition' }); - var policy = new Catbox.Policy(rule, client, 'test-segment'); - - var gen = 0; - - client.start(function () { - - policy.get('test', function (err, value1, cached, report) { - - expect(value1.gen).to.equal(1); // Fresh - setTimeout(function () { - - policy.get('test', function (err, value2, cached, report) { - - // Generates a new one in background which will produce Error and clear the cache - - expect(value2.gen).to.equal(1); // Stale - setTimeout(function () { - - policy.get('test', function (err, value3, cached, report) { - - expect(value3.gen).to.equal(3); // Fresh - done(); - }); - }, 3); - }); - }, 21); - }); - }); - }); - - it('returns stale object then invalidate cache on error when dropOnError is true', function (done) { - - var rule = { - expiresIn: 100, - staleIn: 20, - staleTimeout: 5, - dropOnError: true, - generateFunc: function (id, next) { - - ++gen; - - setTimeout(function () { - - if (gen === 1) { - return next(null, { gen: gen }); - } - - return next(new Error()); - }, 6); - } - }; - - var client = new Catbox.Client(Import, { partition: 'test-partition' }); - var policy = new Catbox.Policy(rule, client, 'test-segment'); - - var gen = 0; - - client.start(function () { - - policy.get('test', function (err, value1, cached, report) { - - expect(value1.gen).to.equal(1); // Fresh - setTimeout(function () { - - policy.get('test', function (err, value2, cached, report) { - - // Generates a new one in background which will produce Error and clear the cache - - expect(value2.gen).to.equal(1); // Stale - setTimeout(function () { - - policy.get('test', function (err, value3, cached, report) { - - expect(err).to.be.instanceof(Error); // Stale - done(); - }); - }, 3); - }); - }, 21); - }); - }); - }); - - it('returns stale object then invalidate cache on error when dropOnError is not set', function (done) { - - var rule = { - expiresIn: 100, - staleIn: 20, - staleTimeout: 5, - generateFunc: function (id, next) { - - ++gen; - - setTimeout(function () { - - if (gen === 1) { - return next(null, { gen: gen }); - } - - return next(new Error()); - }, 6); - } - }; - - var client = new Catbox.Client(Import, { partition: 'test-partition' }); - var policy = new Catbox.Policy(rule, client, 'test-segment'); - - var gen = 0; - - client.start(function () { - - policy.get('test', function (err, value1, cached, report) { - - expect(value1.gen).to.equal(1); // Fresh - setTimeout(function () { - - policy.get('test', function (err, value2, cached, report) { - - // Generates a new one in background which will produce Error and clear the cache - - expect(value2.gen).to.equal(1); // Stale - setTimeout(function () { - - policy.get('test', function (err, value3, cached, report) { - - expect(err).to.be.instanceof(Error); // Stale - done(); - }); - }, 3); - }); - }, 21); - }); - }); - }); - - it('returns stale object then does not invalidate cache on timeout if dropOnError is false', function (done) { - - var rule = { - expiresIn: 100, - staleIn: 20, - staleTimeout: 5, - dropOnError: false, - generateFunc: function (id, next) { - - ++gen; - - setTimeout(function () { - - if (gen === 1) { - return next(null, { gen: gen }); - } - - return next(new Error()); - }, 6); - } - }; - - var client = new Catbox.Client(Import, { partition: 'test-partition' }); - var policy = new Catbox.Policy(rule, client, 'test-segment'); - - var gen = 0; - - client.start(function () { - - policy.get('test', function (err, value1, cached, report) { - - expect(value1.gen).to.equal(1); // Fresh - setTimeout(function () { - - policy.get('test', function (err, value2, cached, report) { - - // Generates a new one in background which will produce Error, but not clear the cache - - expect(value2.gen).to.equal(1); // Stale - setTimeout(function () { - - policy.get('test', function (err, value3, cached, report) { - - expect(value3.gen).to.equal(1); // Stale - done(); - }); - }, 3); - }); - }, 21); - }); - }); - }); - - it('returns stale object then does not invalidate cache on error if dropOnError is false', function (done) { - - var rule = { - expiresIn: 100, - staleIn: 20, - staleTimeout: 5, - dropOnError: false, - generateFunc: function (id, next) { - - ++gen; - - if (gen === 1) { - return next(null, { gen: gen }); - } - - return next(new Error()); - } - }; - - var client = new Catbox.Client(Import, { partition: 'test-partition' }); - var policy = new Catbox.Policy(rule, client, 'test-segment'); - - var gen = 0; - - client.start(function () { - - policy.get('test', function (err, value1, cached) { - - expect(value1.gen).to.equal(1); // Fresh - setTimeout(function () { - policy.get('test', function (err, value2, cached) { - - // Generates a new one in background which will produce Error, but not clear the cache - - expect(value2.gen).to.equal(1); // Stale - - policy.get('test', function (err, value3, cached) { - - expect(value3.gen).to.equal(1); // Stale - done(); - }); - }); - }, 21); - }); - }); - }); - - it('returns stale object then invalidates cache on error if dropOnError is true', function (done) { - - var rule = { - expiresIn: 100, - staleIn: 20, - staleTimeout: 5, - dropOnError: true, - generateFunc: function (id, next) { - - ++gen; - - if (gen === 1) { - return next(null, { gen: gen }); - } - - return next(new Error()); - } - }; - - var client = new Catbox.Client(Import, { partition: 'test-partition' }); - var policy = new Catbox.Policy(rule, client, 'test-segment'); - - var gen = 0; - - client.start(function () { - - policy.get('test', function (err, value1, cached) { - - expect(value1.gen).to.equal(1); // Fresh - setTimeout(function () { - policy.get('test', function (err, value2, cached) { - - // Generates a new one in background which will produce Error, but not clear the cache - expect(err).to.be.instanceOf(Error); - expect(value2).to.be.undefined; // Stale - - policy.get('test', function (err, value3, cached) { - - expect(err).to.be.instanceOf(Error); - expect(value3).to.be.undefined; // Stale - done(); - }); - }); - }, 21); - }); - }); - }); - - - it('returns stale object then invalidates cache on error if dropOnError is not defined', function (done) { - - var rule = { - expiresIn: 100, - staleIn: 20, - staleTimeout: 5, - generateFunc: function (id, next) { - - ++gen; - - if (gen === 1) { - return next(null, { gen: gen }); - } - - return next(new Error()); - } - }; - - var client = new Catbox.Client(Import, { partition: 'test-partition' }); - var policy = new Catbox.Policy(rule, client, 'test-segment'); - - var gen = 0; - - client.start(function () { - - policy.get('test', function (err, value1, cached) { - - expect(value1.gen).to.equal(1); // Fresh - setTimeout(function () { - policy.get('test', function (err, value2, cached) { - - // Generates a new one in background which will produce Error, but not clear the cache - expect(err).to.be.instanceOf(Error); - expect(value2).to.be.undefined; // Stale - - policy.get('test', function (err, value3, cached) { - - expect(err).to.be.instanceOf(Error); - expect(value3).to.be.undefined; // Stale - done(); - }); - }); - }, 21); - }); - }); - }); - - - it('returns fresh objects', function (done) { - - var rule = { - expiresIn: 100, - staleIn: 20, - staleTimeout: 10, - generateFunc: function (id, next) { - - return next(null, { gen: ++gen }); - } - }; - - var client = new Catbox.Client(Import, { partition: 'test-partition' }); - var policy = new Catbox.Policy(rule, client, 'test-segment'); - - var gen = 0; - - client.start(function () { - - policy.get('test', function (err, value1, cached, report) { - - expect(value1.gen).to.equal(1); // Fresh - setTimeout(function () { - - policy.get('test', function (err, value2, cached, report) { - - expect(value2.gen).to.equal(2); // Fresh - - setTimeout(function () { - - policy.get('test', function (err, value3, cached, report) { - - expect(value3.gen).to.equal(2); // Fresh - done(); - }); - }, 1); - }); - }, 21); - }); - }); - }); - - it('returns error when generated within stale timeout', function (done) { - - var rule = { - expiresIn: 30, - staleIn: 20, - staleTimeout: 5, - generateFunc: function (id, next) { - - ++gen; - if (gen !== 2) { - return next(null, { gen: gen }); - } - - return next(new Error()); - } - }; - - var client = new Catbox.Client(Import, { partition: 'test-partition' }); - var policy = new Catbox.Policy(rule, client, 'test-segment'); - - var gen = 0; - - client.start(function () { - - policy.get('test', function (err, value1, cached, report) { - - expect(value1.gen).to.equal(1); // Fresh - setTimeout(function () { - - policy.get('test', function (err, value2, cached, report) { - - // Generates a new one which will produce Error - - expect(err).to.be.instanceof(Error); // Stale - done(); - }); - }, 21); - }); - }); - }); - - it('returns new object when stale has less than staleTimeout time left', function (done) { - - var rule = { - expiresIn: 31, - staleIn: 15, - staleTimeout: 15, - generateFunc: function (id, next) { - - return next(null, { gen: ++gen }); - } - }; - - var client = new Catbox.Client(Import, { partition: 'test-partition' }); - var policy = new Catbox.Policy(rule, client, 'test-segment'); - - var gen = 0; - - client.start(function () { - - policy.get('test', function (err, value1, cached, report) { - - expect(value1.gen).to.equal(1); // Fresh - setTimeout(function () { - - policy.get('test', function (err, value2, cached, report) { - - expect(value2.gen).to.equal(1); // Fresh - setTimeout(function () { - - policy.get('test', function (err, value3, cached, report) { - - expect(value3.gen).to.equal(2); // Fresh - done(); - }); - }, 11); - }); - }, 10); - }); - }); - }); - - it('invalidates cache on error without stale', function (done) { - - var rule = { - expiresIn: 20, - staleIn: 5, - staleTimeout: 5, - generateFunc: function (id, next) { - - ++gen; - - if (gen === 2) { - return next(new Error()); - } - - return next(null, { gen: gen }); - } - }; - - var client = new Catbox.Client(Import, { partition: 'test-partition' }); - var policy = new Catbox.Policy(rule, client, 'test-segment'); - - var gen = 0; - - client.start(function () { - - policy.get('test', function (err, value1, cached, report) { - - expect(value1.gen).to.equal(1); // Fresh - setTimeout(function () { - - policy.get('test', function (err, value2, cached, report) { - - expect(err).to.exist(); - - policy._get('test', function (err, value3) { - - expect(value3).to.equal(null); - done(); - }); - }); - }, 8); - }); - }); - }); - - it('returns timeout error when generate takes too long', function (done) { - - var rule = { - expiresIn: 10, - generateTimeout: 5, - generateFunc: function (id, next) { - - setTimeout(function () { - - return next(null, { gen: ++gen }); - }, 6); - } - }; - - var client = new Catbox.Client(Import, { partition: 'test-partition' }); - var policy = new Catbox.Policy(rule, client, 'test-segment'); - - var gen = 0; - - client.start(function () { - - policy.get('test', function (err, value1, cached, report) { - - expect(err.output.statusCode).to.equal(503); - setTimeout(function () { - - policy.get('test', function (err, value2, cached, report) { - - expect(value2.gen).to.equal(1); - setTimeout(function () { - - policy.get('test', function (err, value3, cached, report) { - - expect(err.output.statusCode).to.equal(503); - done(); - }); - }, 10); - }); - }, 2); - }); - }); - }); - - it('queues requests while pending', function (done) { - - var gen = 0; - var rule = { - expiresIn: 100, - generateFunc: function (id, next) { - - return next(null, { gen: ++gen }); - } - }; - - var client = new Catbox.Client(Import, { partition: 'test-partition' }); - var policy = new Catbox.Policy(rule, client, 'test-segment'); - - client.start(function () { - - var result = null; - var compare = function (err, value, cached, report) { - - if (!result) { - result = value; - return; - } - - expect(result).to.equal(value); - done(); - }; - - policy.get('test', compare); - policy.get('test', compare); - }); - }); - - it('catches errors thrown in generateFunc and passes to all pending requests', function (done) { - - var gen = 0; - var rule = { - expiresIn: 100, - generateFunc: function (id, next) { - - throw new Error('generate failed'); - } - }; - - var client = new Catbox.Client(Import, { partition: 'test-partition' }); - var policy = new Catbox.Policy(rule, client, 'test-segment'); - - client.start(function () { - - var result = null; - var compare = function (err, value, cached, report) { - - if (!result) { - result = err; - return; - } - - expect(result).to.equal(err); - expect(err.message).to.equal('generate failed'); - done(); - }; - - policy.get('test', compare); - policy.get('test', compare); - }); - }); - - it('does not return stale value from previous request timeout left behind', { parallel: false }, function (done) { - - var gen = 0; - - var rule = { - expiresIn: 100, - staleIn: 20, - staleTimeout: 10, - generateFunc: function (id, next) { - - setTimeout(function () { - - next(null, { gen: ++gen }); - }, 5) - } - }; - - var client = new Catbox.Client(Import, { partition: 'test-partition' }); - - var orig = client.connection.get; - client.connection.get = function (key, callback) { // Delayed get - - setTimeout(function () { - - orig.call(client.connection, key, callback) - }, 10) - }; - - var policy = new Catbox.Policy(rule, client, 'test-segment'); - - client.start(function () { - - policy.get('test', function (err, value1, cached, report) { // Cache lookup takes 10 + generate 5 - - expect(value1.gen).to.equal(1); // Fresh - setTimeout(function () { // Wait for stale - - policy.get('test', function (err, value2, cached, report) { // Cache lookup takes 10, generate comes back after 5 - - expect(value2.gen).to.equal(2); // Fresh - policy.get('test', function (err, value3, cached, report) { // Cache lookup takes 10 - - expect(value3.gen).to.equal(2); // Cached (10 left to stale) - - client.connection.get = orig; - done() - }) - }); - }, 21); - }); - }); - }); - }); - }); - - describe('drop()', function () { - - it('calls the extension clients drop function', function (done) { - - var engine = { - start: function (callback) { - - callback(); - }, - isReady: function () { - - return true; - }, - drop: function (key, callback) { - - callback(null, 'success'); - }, - validateSegmentName: function () { - - return null; - } - }; - - var policyConfig = { - expiresIn: 50000 - }; - - var client = new Catbox.Client(engine); - var policy = new Catbox.Policy(policyConfig, client, 'test'); - - policy.drop('test', function (err, result) { - - expect(result).to.equal('success'); - done(); - }); - }); - }); - - describe('ttl()', function () { - - it('returns the ttl factoring in the created time', function (done) { - - var engine = { - start: function (callback) { - - callback(); - }, - isReady: function () { - - return true; - }, - validateSegmentName: function () { - - return null; - } - }; - - var policyConfig = { - expiresIn: 50000 - }; - - var client = new Catbox.Client(engine); - var policy = new Catbox.Policy(policyConfig, client, 'test'); - - var result = policy.ttl(Date.now() - 10000); - expect(result).to.be.within(39999, 40001); // There can occasionally be a 1ms difference - done(); - }); - - it('returns expired when created in the future', function (done) { - - var config = { - expiresAt: '10:00' - }; - - var rules = new Catbox.Policy.compile(config); - - var created = new Date('Sat Sep 06 2014 13:00:00').getTime(); - var now = new Date('Sat Sep 06 2014 12:00:00').getTime(); - - var ttl = Catbox.Policy.ttl(rules, created, now); - expect(ttl).to.equal(0); - done(); - }); - - it('returns expired on c-e-n same day', function (done) { - - var config = { - expiresAt: '10:00' - }; - - var rules = new Catbox.Policy.compile(config); - - var created = new Date('Sat Sep 06 2014 9:00:00').getTime(); - var now = new Date('Sat Sep 06 2014 11:00:00').getTime(); - - var ttl = Catbox.Policy.ttl(rules, created, now); - expect(ttl).to.equal(0); - done(); - }); - - it('returns expired on c-(midnight)-e-n', function (done) { - - var config = { - expiresAt: '10:00' - }; - - var rules = new Catbox.Policy.compile(config); - - var created = new Date('Sat Sep 06 2014 11:00:00').getTime(); - var now = new Date('Sat Sep 07 2014 10:00:01').getTime(); - - var ttl = Catbox.Policy.ttl(rules, created, now); - expect(ttl).to.equal(0); - done(); - }); - - it('returns ttl on c-n-e same day', function (done) { - - var config = { - expiresAt: '10:00' - }; - - var rules = new Catbox.Policy.compile(config); - - var created = new Date('Sat Sep 06 2014 9:00:00').getTime(); - var now = new Date('Sat Sep 06 2014 9:30:00').getTime(); - - var ttl = Catbox.Policy.ttl(rules, created, now); - expect(ttl).to.equal(30 * 60 * 1000); - done(); - }); - - it('returns ttl on c-(midnight)-n-e', function (done) { - - var config = { - expiresAt: '10:00' - }; - - var rules = new Catbox.Policy.compile(config); - - var created = new Date('Sat Sep 06 2014 11:00:00').getTime(); - var now = new Date('Sat Sep 07 2014 9:00:00').getTime(); - - var ttl = Catbox.Policy.ttl(rules, created, now); - expect(ttl).to.equal(60 * 60 * 1000); - done(); - }); - }); - - describe('compile()', function () { - - it('does not try to compile a null config', function (done) { - - var rule = Catbox.policy.compile(null); - expect(rule).to.deep.equal({}); - done(); - }); - - it('compiles a single rule', function (done) { - - var config = { - expiresIn: 50000 - }; - - var rule = Catbox.policy.compile(config, false); - expect(rule.expiresIn).to.equal(config.expiresIn); - done(); - }); - - it('ignores external options', function (done) { - - var config = { - expiresIn: 50000, - cache: true - }; - - var rule = Catbox.policy.compile(config, false); - expect(rule.expiresIn).to.equal(config.expiresIn); - done(); - }); - - it('assigns the expiresIn when the rule is cached', function (done) { - - var config = { - expiresIn: 50000 - }; - - var rule = Catbox.policy.compile(config, false); - expect(rule.expiresIn).to.equal(config.expiresIn); - done(); - }); - - it('allows a rule with neither expiresAt or expiresIn', function (done) { - - var fn = function () { - - Catbox.policy.compile({ cache: 1 }, true); - }; - - expect(fn).to.not.throw(); - done(); - }); - - it('allows a rule with expiresAt and undefined expiresIn', function (done) { - - var fn = function () { - - Catbox.policy.compile({ expiresIn: undefined, expiresAt: '09:00' }, true); - }; - - expect(fn).to.not.throw(); - done(); - }); - - it('allows combination of expiresIn, staleTimeout and staleIn function', function (done) { - - var staleIn = function (stored, ttl) { - - return 1000; - }; - - var config = { - expiresIn: 500000, - staleIn: staleIn, - staleTimeout: 500, - generateFunc: function () { } - }; - - var fn = function () { - - Catbox.policy.compile(config, true); - }; - - expect(fn).to.not.throw(); - done(); - }); - - it('throws an error when staleIn is greater than expiresIn', function (done) { - - var config = { - expiresIn: 500000, - staleIn: 1000000, - staleTimeout: 500, - generateFunc: function () { } - }; - - var fn = function () { - - Catbox.policy.compile(config, true); - }; - - expect(fn).to.throw('staleIn must be less than expiresIn'); - done(); - }); - - it('throws an error when staleTimeout is greater than expiresIn', function (done) { - - var config = { - expiresIn: 500000, - staleIn: 100000, - staleTimeout: 500000, - generateFunc: function () { } - }; - - var fn = function () { - - Catbox.policy.compile(config, true); - }; - - expect(fn).to.throw('staleTimeout must be less than expiresIn'); - done(); - }); - - it('throws an error when staleTimeout is greater than expiresIn - staleIn', function (done) { - - var config = { - expiresIn: 30000, - staleIn: 20000, - staleTimeout: 10000, - generateFunc: function () { } - }; - - var fn = function () { - - Catbox.policy.compile(config, true); - }; - - expect(fn).to.throw('staleTimeout must be less than the delta between expiresIn and staleIn'); - done(); - }); - - it('throws an error when staleTimeout is used without server mode', function (done) { - - var config = { - expiresIn: 1000000, - staleIn: 500000, - staleTimeout: 500, - generateFunc: function () { } - }; - - var fn = function () { - - var policy = new Catbox.Policy(config); - }; - - expect(fn).to.throw('Cannot use stale options without server-side caching'); - done(); - }); - - it('returns rule when staleIn is less than expiresIn', function (done) { - - var config = { - expiresIn: 1000000, - staleIn: 500000, - staleTimeout: 500, - generateFunc: function () { } - }; - - var rule = Catbox.policy.compile(config, true); - expect(rule.staleIn).to.equal(500 * 1000); - expect(rule.expiresIn).to.equal(1000 * 1000); - done(); - }); - - it('returns rule when staleIn is less than 24 hours and using expiresAt', function (done) { - - var config = { - expiresAt: '03:00', - staleIn: 5000000, - staleTimeout: 500, - generateFunc: function () { } - }; - - var rule = Catbox.policy.compile(config, true); - expect(rule.staleIn).to.equal(5000 * 1000); - done(); - }); - - it('does not throw an error if has both staleTimeout and staleIn', function (done) { - - var config = { - staleIn: 30000, - staleTimeout: 300, - expiresIn: 60000, - generateFunc: function () { } - }; - - var fn = function () { - - Catbox.policy.compile(config, true); - }; - expect(fn).to.not.throw(); - done(); - }); - - it('throws an error if trying to use stale caching on the client', function (done) { - - var config = { - staleIn: 30000, - expiresIn: 60000, - staleTimeout: 300, - generateFunc: function () { } - }; - - var fn = function () { - - Catbox.policy.compile(config, false); - }; - - expect(fn).to.throw('Cannot use stale options without server-side caching'); - done(); - }); - - it('converts the stale time to ms', function (done) { - - var config = { - staleIn: 30000, - expiresIn: 60000, - staleTimeout: 300, - generateFunc: function () { } - }; - - var rule = Catbox.policy.compile(config, true); - - expect(rule.staleIn).to.equal(config.staleIn); - done(); - }); - - it('throws an error if staleTimeout is greater than expiresIn', function (done) { - - var config = { - staleIn: 2000, - expiresIn: 10000, - staleTimeout: 30000, - generateFunc: function () { } - }; - - var fn = function () { - - Catbox.policy.compile(config, true); - }; - - expect(fn).to.throw('staleTimeout must be less than expiresIn'); - done(); - }); - - it('throws an error if staleIn is greater than expiresIn', function (done) { - - var config = { - staleIn: 1000000, - expiresIn: 60000, - staleTimeout: 30, - generateFunc: function () { } - }; - - var fn = function () { - - Catbox.policy.compile(config, false); - }; - - expect(fn).to.throw('staleIn must be less than expiresIn'); - done(); - }); - }); - - describe('ttl()', function () { - - it('returns zero when a rule is expired', function (done) { - - var config = { - expiresIn: 50000 - }; - var rule = Catbox.policy.compile(config, false); - var created = new Date(Date.now()); - created = created.setMinutes(created.getMinutes() - 5); - - var ttl = Catbox.policy.ttl(rule, created); - expect(ttl).to.be.equal(0); - done(); - }); - - it('returns a positive number when a rule is not expired', function (done) { - - var config = { - expiresIn: 50000 - }; - var rule = Catbox.policy.compile(config, false); - var created = new Date(Date.now()); - - var ttl = Catbox.policy.ttl(rule, created); - expect(ttl).to.be.greaterThan(0); - done(); - }); - - it('returns the correct expires time when no created time is provided', function (done) { - - var config = { - expiresIn: 50000 - }; - var rule = Catbox.policy.compile(config, false); - - var ttl = Catbox.policy.ttl(rule); - expect(ttl).to.equal(50000); - done(); - }); - - it('returns 0 when created several days ago and expiresAt is used', function (done) { - - var config = { - expiresAt: '13:00' - }; - var created = Date.now() - 313200000; // 87 hours (3 days + 15 hours) - var rule = Catbox.policy.compile(config, false); - - var ttl = Catbox.policy.ttl(rule, created); - expect(ttl).to.equal(0); - done(); - }); - - it('returns 0 when created in the future', function (done) { - - var config = { - expiresIn: 100 - }; - var created = Date.now() + 1000; - var rule = Catbox.policy.compile(config, false); - - var ttl = Catbox.policy.ttl(rule, created); - expect(ttl).to.equal(0); - done(); - }); - - it('returns 0 for bad rule', function (done) { - - var created = Date.now() - 1000; - var ttl = Catbox.policy.ttl({}, created); - expect(ttl).to.equal(0); - done(); - }); - - it('returns 0 when created 60 hours ago and expiresAt is used with an hour before the created hour', function (done) { - - var config = { - expiresAt: '12:00' - }; - var created = Date.now() - 342000000; // 95 hours ago (3 days + 23 hours) - var rule = Catbox.policy.compile(config, false); - - var ttl = Catbox.policy.ttl(rule, created); - expect(ttl).to.equal(0); - done(); - }); - - it('returns a positive number when using a future expiresAt', function (done) { - - var hour = new Date(Date.now() + 60 * 60 * 1000).getHours(); - hour = hour === 0 ? 1 : hour; - - var config = { - expiresAt: hour + ':00' - }; - - var rule = Catbox.policy.compile(config, false); - - var ttl = Catbox.policy.ttl(rule); - expect(ttl).to.be.greaterThan(0); - done(); - }); - - it('returns the correct number when using a future expiresAt', function (done) { - - var twoHoursAgo = new Date(Date.now() - 2 * 60 * 60 * 1000); - var hours = twoHoursAgo.getHours(); - var minutes = '' + twoHoursAgo.getMinutes(); - var created = twoHoursAgo.getTime() + (60 * 60 * 1000); - minutes = minutes.length === 1 ? '0' + minutes : minutes; - - var config = { - expiresAt: hours + ':' + minutes - }; - - var rule = Catbox.policy.compile(config, false); - var ttl = Catbox.policy.ttl(rule, created); - - expect(ttl).to.be.about(22 * 60 * 60 * 1000, 60 * 1000); - done(); - }); - - it('returns correct number when using an expiresAt time tomorrow', function (done) { - - var hour = new Date(Date.now() - 60 * 60 * 1000).getHours(); - - var config = { - expiresAt: hour + ':00' - }; - - var rule = Catbox.policy.compile(config, false); - - var ttl = Catbox.policy.ttl(rule); - expect(ttl).to.be.about(23 * 60 * 60 * 1000, 60 * 60 * 1000); - done(); - }); - - it('returns correct number when using a created time from yesterday and expires in 2 hours', function (done) { - - var hour = new Date(Date.now() + 2 * 60 * 60 * 1000).getHours(); - - var config = { - expiresAt: hour + ':00' - }; - var created = new Date(Date.now()); - created.setHours(new Date(Date.now()).getHours() - 22); - - var rule = Catbox.policy.compile(config, false); - - var ttl = Catbox.policy.ttl(rule, created); - expect(ttl).to.be.about(60 * 60 * 1000, 60 * 60 * 1000); - done(); - }); - }); -}); - - diff --git a/node_modules/hapi/node_modules/cryptiles/.npmignore b/node_modules/hapi/node_modules/cryptiles/.npmignore deleted file mode 100644 index 77ba16c..0000000 --- a/node_modules/hapi/node_modules/cryptiles/.npmignore +++ /dev/null @@ -1,18 +0,0 @@ -.idea -*.iml -npm-debug.log -dump.rdb -node_modules -results.tap -results.xml -npm-shrinkwrap.json -config.json -.DS_Store -*/.DS_Store -*/*/.DS_Store -._* -*/._* -*/*/._* -coverage.* -lib-cov - diff --git a/node_modules/hapi/node_modules/cryptiles/.travis.yml b/node_modules/hapi/node_modules/cryptiles/.travis.yml deleted file mode 100755 index 047f7e3..0000000 --- a/node_modules/hapi/node_modules/cryptiles/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: node_js - -node_js: - - 0.10 - diff --git a/node_modules/hapi/node_modules/cryptiles/LICENSE b/node_modules/hapi/node_modules/cryptiles/LICENSE deleted file mode 100755 index cda4473..0000000 --- a/node_modules/hapi/node_modules/cryptiles/LICENSE +++ /dev/null @@ -1,28 +0,0 @@ -Copyright (c) 2014, Eran Hammer and other contributors. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The names of any contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - * * * - -The complete list of contributors can be found at: https://github.com/hueniverse/cryptiles/graphs/contributors diff --git a/node_modules/hapi/node_modules/cryptiles/Makefile b/node_modules/hapi/node_modules/cryptiles/Makefile deleted file mode 100755 index 3a89298..0000000 --- a/node_modules/hapi/node_modules/cryptiles/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -test: - node node_modules/lab/bin/lab -test-cov: - node node_modules/lab/bin/lab -t 100 -test-cov-html: - node node_modules/lab/bin/lab -r html -o coverage.html - -.PHONY: test test-cov test-cov-html - diff --git a/node_modules/hapi/node_modules/cryptiles/README.md b/node_modules/hapi/node_modules/cryptiles/README.md deleted file mode 100644 index be943f8..0000000 --- a/node_modules/hapi/node_modules/cryptiles/README.md +++ /dev/null @@ -1,14 +0,0 @@ -cryptiles -========= - -General purpose crypto utilities - -[![Build Status](https://secure.travis-ci.org/hapijs/cryptiles.png)](http://travis-ci.org/hapijs/cryptiles) - -## Methods - -### `randomString( size)` -Returns a cryptographically strong pseudo-random data string. Takes a size argument for the length of the string. - -### `fixedTimeComparison( a, b)` -Compare two strings using fixed time algorithm (to prevent time-based analysis of MAC digest match). Returns `true` if the strings match, `false` if they differ. diff --git a/node_modules/hapi/node_modules/cryptiles/index.js b/node_modules/hapi/node_modules/cryptiles/index.js deleted file mode 100755 index 4cc88b3..0000000 --- a/node_modules/hapi/node_modules/cryptiles/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./lib'); \ No newline at end of file diff --git a/node_modules/hapi/node_modules/cryptiles/package.json b/node_modules/hapi/node_modules/cryptiles/package.json deleted file mode 100644 index 6a140dc..0000000 --- a/node_modules/hapi/node_modules/cryptiles/package.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "name": "cryptiles", - "description": "General purpose crypto utilities", - "version": "2.0.4", - "author": { - "name": "Eran Hammer", - "email": "eran@hammer.io", - "url": "http://hueniverse.com" - }, - "contributors": [], - "repository": { - "type": "git", - "url": "git://github.com/hapijs/cryptiles.git" - }, - "main": "index", - "keywords": [ - "cryptography", - "security", - "utilites" - ], - "engines": { - "node": ">=0.8.0" - }, - "dependencies": { - "boom": "2.x.x" - }, - "devDependencies": { - "lab": "4.x.x" - }, - "scripts": { - "test": "make test-cov" - }, - "licenses": [ - { - "type": "BSD", - "url": "http://github.com/hapijs/cryptiles/raw/master/LICENSE" - } - ], - "gitHead": "944263dbb628b9b3da542d35600d587f861eeaf0", - "bugs": { - "url": "https://github.com/hapijs/cryptiles/issues" - }, - "homepage": "https://github.com/hapijs/cryptiles", - "_id": "cryptiles@2.0.4", - "_shasum": "09ea1775b9e1c7de7e60a99d42ab6f08ce1a1285", - "_from": "cryptiles@2.0.4", - "_npmVersion": "1.4.23", - "_npmUser": { - "name": "hueniverse", - "email": "eran@hueniverse.com" - }, - "maintainers": [ - { - "name": "hueniverse", - "email": "eran@hueniverse.com" - } - ], - "dist": { - "shasum": "09ea1775b9e1c7de7e60a99d42ab6f08ce1a1285", - "tarball": "http://registry.npmjs.org/cryptiles/-/cryptiles-2.0.4.tgz" - }, - "directories": {}, - "_resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.4.tgz", - "readme": "ERROR: No README data found!" -} diff --git a/node_modules/hapi/node_modules/cryptiles/test/index.js b/node_modules/hapi/node_modules/cryptiles/test/index.js deleted file mode 100755 index 3340141..0000000 --- a/node_modules/hapi/node_modules/cryptiles/test/index.js +++ /dev/null @@ -1,108 +0,0 @@ -// Load modules - -var Lab = require('lab'); -var Cryptiles = require('../lib'); - - -// Declare internals - -var internals = {}; - - -// Test shortcuts - -var lab = exports.lab = Lab.script(); -var before = lab.before; -var after = lab.after; -var describe = lab.experiment; -var it = lab.test; -var expect = Lab.expect; - - -describe('Cryptiles', function () { - - describe('#randomString', function () { - - it('should generate the right length string', function (done) { - - for (var i = 1; i <= 1000; ++i) { - expect(Cryptiles.randomString(i).length).to.equal(i); - } - - done(); - }); - - it('returns an error on invalid bits size', function (done) { - - expect(Cryptiles.randomString(99999999999999999999).message).to.equal('Failed generating random bits: Argument #1 must be number > 0'); - done(); - }); - }); - - describe('#randomBits', function () { - - it('returns an error on invalid input', function (done) { - - expect(Cryptiles.randomBits(0).message).to.equal('Invalid random bits count'); - done(); - }); - }); - - describe('#fixedTimeComparison', function () { - - var a = Cryptiles.randomString(50000); - var b = Cryptiles.randomString(150000); - - it('should take the same amount of time comparing different string sizes', function (done) { - - var now = Date.now(); - Cryptiles.fixedTimeComparison(b, a); - var t1 = Date.now() - now; - - now = Date.now(); - Cryptiles.fixedTimeComparison(b, b); - var t2 = Date.now() - now; - - expect(t2 - t1).to.be.within(-20, 20); - done(); - }); - - it('should return true for equal strings', function (done) { - - expect(Cryptiles.fixedTimeComparison(a, a)).to.equal(true); - done(); - }); - - it('should return false for different strings (size, a < b)', function (done) { - - expect(Cryptiles.fixedTimeComparison(a, a + 'x')).to.equal(false); - done(); - }); - - it('should return false for different strings (size, a > b)', function (done) { - - expect(Cryptiles.fixedTimeComparison(a + 'x', a)).to.equal(false); - done(); - }); - - it('should return false for different strings (size, a = b)', function (done) { - - expect(Cryptiles.fixedTimeComparison(a + 'x', a + 'y')).to.equal(false); - done(); - }); - - it('should return false when not a string', function (done) { - - expect(Cryptiles.fixedTimeComparison('x', null)).to.equal(false); - done(); - }); - - it('should return false when not a string (left)', function (done) { - - expect(Cryptiles.fixedTimeComparison(null, 'x')).to.equal(false); - done(); - }); - }); -}); - - diff --git a/node_modules/hapi/node_modules/hoek/.npmignore b/node_modules/hapi/node_modules/hoek/.npmignore deleted file mode 100644 index 7e1574d..0000000 --- a/node_modules/hapi/node_modules/hoek/.npmignore +++ /dev/null @@ -1,18 +0,0 @@ -.idea -*.iml -npm-debug.log -dump.rdb -node_modules -results.tap -results.xml -npm-shrinkwrap.json -config.json -.DS_Store -*/.DS_Store -*/*/.DS_Store -._* -*/._* -*/*/._* -coverage.* -lib-cov -complexity.md diff --git a/node_modules/hapi/node_modules/hoek/.travis.yml b/node_modules/hapi/node_modules/hoek/.travis.yml deleted file mode 100755 index c84aade..0000000 --- a/node_modules/hapi/node_modules/hoek/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: node_js - -node_js: - - 0.10 - - 0.12 - - iojs - diff --git a/node_modules/hapi/node_modules/hoek/LICENSE b/node_modules/hapi/node_modules/hoek/LICENSE deleted file mode 100755 index 5530904..0000000 --- a/node_modules/hapi/node_modules/hoek/LICENSE +++ /dev/null @@ -1,31 +0,0 @@ -Copyright (c) 2011-2014, Walmart and other contributors. -Copyright (c) 2011, Yahoo Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The names of any contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - * * * - -The complete list of contributors can be found at: https://github.com/hapijs/hapi/graphs/contributors -Portions of this project were initially based on the Yahoo! Inc. Postmile project, -published at https://github.com/yahoo/postmile. diff --git a/node_modules/hapi/node_modules/hoek/Makefile b/node_modules/hapi/node_modules/hoek/Makefile deleted file mode 100755 index 83aaf0c..0000000 --- a/node_modules/hapi/node_modules/hoek/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -test: - @node node_modules/lab/bin/lab -a code -test-cov: - @node node_modules/lab/bin/lab -a code -t 100 -L -test-cov-html: - @node node_modules/lab/bin/lab -a code -r html -o coverage.html - -.PHONY: test test-cov test-cov-html diff --git a/node_modules/hapi/node_modules/hoek/README.md b/node_modules/hapi/node_modules/hoek/README.md deleted file mode 100755 index 19357bb..0000000 --- a/node_modules/hapi/node_modules/hoek/README.md +++ /dev/null @@ -1,574 +0,0 @@ -![hoek Logo](https://raw.github.com/hapijs/hoek/master/images/hoek.png) - -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). - -[![Build Status](https://secure.travis-ci.org/hapijs/hoek.png)](http://travis-ci.org/hapijs/hoek) - -Lead Maintainer: [Nathan LaFreniere](https://github.com/nlf) - -# Table of Contents - -* [Introduction](#introduction "Introduction") -* [Object](#object "Object") - * [clone](#cloneobj "clone") - * [cloneWithShallow](#clonewithshallowobj-keys "cloneWithShallow") - * [merge](#mergetarget-source-isnulloverride-ismergearrays "merge") - * [applyToDefaults](#applytodefaultsdefaults-options-isnulloverride "applyToDefaults") - * [applyToDefaultsWithShallow](#applytodefaultswithshallowdefaults-options-keys "applyToDefaultsWithShallow") - * [deepEqual](#deepequala-b "deepEqual") - * [unique](#uniquearray-key "unique") - * [mapToObject](#maptoobjectarray-key "mapToObject") - * [intersect](#intersectarray1-array2 "intersect") - * [contain](#containref-values-options "contain") - * [flatten](#flattenarray-target "flatten") - * [reach](#reachobj-chain-options "reach") - * [reachTemplate](#reachobj-template-options "reachTemplate") - * [transform](#transformobj-transform-options "transform") - * [shallow](#shallowobj "shallow") - * [stringify](#stringifyobj "stringify") -* [Timer](#timer "Timer") -* [Bench](#bench "Bench") -* [Binary Encoding/Decoding](#binary-encodingdecoding "Binary Encoding/Decoding") - * [base64urlEncode](#base64urlencodevalue "binary64urlEncode") - * [base64urlDecode](#base64urldecodevalue "binary64urlDecode") -* [Escaping Characters](#escaping-characters "Escaping Characters") - * [escapeHtml](#escapehtmlstring "escapeHtml") - * [escapeHeaderAttribute](#escapeheaderattributeattribute "escapeHeaderAttribute") - * [escapeRegex](#escaperegexstring "escapeRegex") -* [Errors](#errors "Errors") - * [assert](#assertcondition-message "assert") - * [abort](#abortmessage "abort") - * [displayStack](#displaystackslice "displayStack") - * [callStack](#callstackslice "callStack") -* [Function](#function "Function") - * [nextTick](#nexttickfn "nextTick") - * [once](#oncefn "once") - * [ignore](#ignore "ignore") -* [Miscellaneous](#miscellaneous "Miscellaneous") - * [uniqueFilename](#uniquefilename "uniqueFilename") - * [isInteger](#isInteger "isInteger") - - - -# Introduction - -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. - -For example, to use Hoek to set configuration with default options: -```javascript -var Hoek = require('hoek'); - -var default = {url : "www.github.com", port : "8000", debug : true}; - -var config = Hoek.applyToDefaults(default, {port : "3000", admin : true}); - -// In this case, config would be { url: 'www.github.com', port: '3000', debug: true, admin: true } -``` - -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. - -## Object - -Hoek provides several helpful methods for objects and arrays. - -### clone(obj) - -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). - -```javascript - -var nestedObj = { - w: /^something$/ig, - x: { - a: [1, 2, 3], - b: 123456, - c: new Date() - }, - y: 'y', - z: new Date() - }; - -var copy = Hoek.clone(nestedObj); - -copy.x.b = 100; - -console.log(copy.y); // results in 'y' -console.log(nestedObj.x.b); // results in 123456 -console.log(copy.x.b); // results in 100 -``` - -### cloneWithShallow(obj, keys) -keys is an array of key names to shallow copy - -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. - -```javascript - -var nestedObj = { - w: /^something$/ig, - x: { - a: [1, 2, 3], - b: 123456, - c: new Date() - }, - y: 'y', - z: new Date() - }; - -var copy = Hoek.cloneWithShallow(nestedObj, ['x']); - -copy.x.b = 100; - -console.log(copy.y); // results in 'y' -console.log(nestedObj.x.b); // results in 100 -console.log(copy.x.b); // results in 100 -``` - -### merge(target, source, isNullOverride, isMergeArrays) -isNullOverride, isMergeArrays default to true - -Merge all the properties of source into target, source wins in conflict, and by default null and undefined from source are applied. -Merge is destructive where the target is modified. For non destructive merge, use `applyToDefaults`. - - -```javascript - -var target = {a: 1, b : 2}; -var source = {a: 0, c: 5}; -var source2 = {a: null, c: 5}; - -Hoek.merge(target, source); // results in {a: 0, b: 2, c: 5} -Hoek.merge(target, source2); // results in {a: null, b: 2, c: 5} -Hoek.merge(target, source2, false); // results in {a: 1, b: 2, c: 5} - -var targetArray = [1, 2, 3]; -var sourceArray = [4, 5]; - -Hoek.merge(targetArray, sourceArray); // results in [1, 2, 3, 4, 5] -Hoek.merge(targetArray, sourceArray, true, false); // results in [4, 5] -``` - -### applyToDefaults(defaults, options, isNullOverride) -isNullOverride defaults to false - -Apply options to a copy of the defaults - -```javascript - -var defaults = { host: "localhost", port: 8000 }; -var options = { port: 8080 }; - -var config = Hoek.applyToDefaults(defaults, options); // results in { host: "localhost", port: 8080 } -``` - -Apply options with a null value to a copy of the defaults - -```javascript - -var defaults = { host: "localhost", port: 8000 }; -var options = { host: null, port: 8080 }; - -var config = Hoek.applyToDefaults(defaults, options, true); // results in { host: null, port: 8080 } -``` - -### applyToDefaultsWithShallow(defaults, options, keys) -keys is an array of key names to shallow copy - -Apply options to a copy of the defaults. Keys specified in the last parameter are shallow copied from options instead of merged. - -```javascript - -var defaults = { - server: { - host: "localhost", - port: 8000 - }, - name: 'example' - }; - -var options = { server: { port: 8080 } }; - -var config = Hoek.applyToDefaults(defaults, options); // results in { server: { port: 8080 }, name: 'example' } -``` - -### deepEqual(b, a, [options]) - -Performs a deep comparison of the two values including support for circular dependencies, prototype, and properties. To skip prototype comparisons, use `options.prototype = false` - -```javascript -Hoek.deepEqual({ a: [1, 2], b: 'string', c: { d: true } }, { a: [1, 2], b: 'string', c: { d: true } }); //results in true -Hoek.deepEqual(Object.create(null), {}, { prototype: false }); //results in true -Hoek.deepEqual(Object.create(null), {}); //results in false -``` - -### unique(array, key) - -Remove duplicate items from Array - -```javascript - -var array = [1, 2, 2, 3, 3, 4, 5, 6]; - -var newArray = Hoek.unique(array); // results in [1,2,3,4,5,6] - -array = [{id: 1}, {id: 1}, {id: 2}]; - -newArray = Hoek.unique(array, "id"); // results in [{id: 1}, {id: 2}] -``` - -### mapToObject(array, key) - -Convert an Array into an Object - -```javascript - -var array = [1,2,3]; -var newObject = Hoek.mapToObject(array); // results in [{"1": true}, {"2": true}, {"3": true}] - -array = [{id: 1}, {id: 2}]; -newObject = Hoek.mapToObject(array, "id"); // results in [{"id": 1}, {"id": 2}] -``` - -### intersect(array1, array2) - -Find the common unique items in two arrays - -```javascript - -var array1 = [1, 2, 3]; -var array2 = [1, 4, 5]; - -var newArray = Hoek.intersect(array1, array2); // results in [1] -``` - -### contain(ref, values, [options]) - -Tests if the reference value contains the provided values where: -- `ref` - the reference string, array, or object. -- `values` - a single or array of values to find within the `ref` value. If `ref` is an object, `values` can be a key name, - an array of key names, or an object with key-value pairs to compare. -- `options` - an optional object with the following optional settings: - - `deep` - if `true`, performed a deep comparison of the values. - - `once` - if `true`, allows only one occurrence of each value. - - `only` - if `true`, does not allow values not explicitly listed. - - `part` - if `true`, allows partial match of the values (at least one must always match). - -Note: comparing a string to overlapping values will result in failed comparison (e.g. `contain('abc', ['ab', 'bc'])`). -Also, if an object key's value does not match the provided value, `false` is returned even when `part` is specified. - -```javascript -Hoek.contain('aaa', 'a', { only: true }); // true -Hoek.contain([{ a: 1 }], [{ a: 1 }], { deep: true }); // true -Hoek.contain([1, 2, 2], [1, 2], { once: true }); // false -Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 1, d: 4 }, { part: true }); // true -``` - -### flatten(array, [target]) - -Flatten an array - -```javascript - -var array = [1, [2, 3]]; - -var flattenedArray = Hoek.flatten(array); // results in [1, 2, 3] - -array = [1, [2, 3]]; -target = [4, [5]]; - -flattenedArray = Hoek.flatten(array, target); // results in [4, [5], 1, 2, 3] -``` - -### reach(obj, chain, [options]) - -Converts an object key chain string to reference - -- `options` - optional settings - - `separator` - string to split chain path on, defaults to '.' - - `default` - value to return if the path or value is not present, default is `undefined` - - `strict` - if `true`, will throw an error on missing member, default is `false` - - `functions` - if `true` allow traversing functions for properties. `false` will throw an error if a function is part of the chain. - -A chain including negative numbers will work like negative indices on an -array. - -```javascript - -var chain = 'a.b.c'; -var obj = {a : {b : { c : 1}}}; - -Hoek.reach(obj, chain); // returns 1 - -var chain = 'a.b.-1'; -var obj = {a : {b : [2,3,6]}}; - -Hoek.reach(obj, chain); // returns 6 -``` - -### reachTemplate(obj, template, [options]) - -Replaces string parameters (`{name}`) with their corresponding object key values by applying the -(`reach()`)[#reachobj-chain-options] method where: - -- `obj` - the context object used for key lookup. -- `template` - a string containing `{}` parameters. -- `options` - optional (`reach()`)[#reachobj-chain-options] options. - -```javascript - -var chain = 'a.b.c'; -var obj = {a : {b : { c : 1}}}; - -Hoek.reachTemplate(obj, '1+{a.b.c}=2'); // returns '1+1=2' -``` - -### transform(obj, transform, [options]) - -Transforms an existing object into a new one based on the supplied `obj` and `transform` map. `options` are the same as the `reach` options. - -```javascript -var source = { - address: { - one: '123 main street', - two: 'PO Box 1234' - }, - title: 'Warehouse', - state: 'CA' -}; - -var result = Hoek.transform(source, { - 'person.address.lineOne': 'address.one', - 'person.address.lineTwo': 'address.two', - 'title': 'title', - 'person.address.region': 'state' -}); -// Results in -// { -// person: { -// address: { -// lineOne: '123 main street', -// lineTwo: 'PO Box 1234', -// region: 'CA' -// } -// }, -// title: 'Warehouse' -// } -``` - -### shallow(obj) - -Performs a shallow copy by copying the references of all the top level children where: -- `obj` - the object to be copied. - -```javascript -var shallow = Hoek.shallow({ a: { b: 1 } }); -``` - -### stringify(obj) - -Converts an object to string using the built-in `JSON.stringify()` method with the difference that any errors are caught -and reported back in the form of the returned string. Used as a shortcut for displaying information to the console (e.g. in -error message) without the need to worry about invalid conversion. - -```javascript -var a = {}; -a.b = a; -Hoek.stringify(a); // Returns '[Cannot display object: Converting circular structure to JSON]' -``` - -# Timer - -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. - -```javascript - -var timerObj = new Hoek.Timer(); -console.log("Time is now: " + timerObj.ts); -console.log("Elapsed time from initialization: " + timerObj.elapsed() + 'milliseconds'); -``` - - -# Bench - -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 -human-readable timestamps. More accurate for benchmarking or internal timers. - -# Binary Encoding/Decoding - -### base64urlEncode(value) - -Encodes value in Base64 or URL encoding - -### base64urlDecode(value) - -Decodes data in Base64 or URL encoding. -# Escaping Characters - -Hoek provides convenient methods for escaping html characters. The escaped characters are as followed: - -```javascript - -internals.htmlEscaped = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''', - '`': '`' -}; -``` - -### escapeHtml(string) - -```javascript - -var string = ' hey '; -var escapedString = Hoek.escapeHtml(string); // returns <html> hey </html> -``` - -### escapeHeaderAttribute(attribute) - -Escape attribute value for use in HTTP header - -```javascript - -var a = Hoek.escapeHeaderAttribute('I said "go w\\o me"'); //returns I said \"go w\\o me\" -``` - - -### escapeRegex(string) - -Escape string for Regex construction - -```javascript - -var a = Hoek.escapeRegex('4^f$s.4*5+-_?%=#!:@|~\\/`"(>)[<]d{}s,'); // returns 4\^f\$s\.4\*5\+\-_\?%\=#\!\:@\|~\\\/`"\(>\)\[<\]d\{\}s\, -``` - -# Errors - -### assert(condition, message) - -```javascript - -var a = 1, b = 2; - -Hoek.assert(a === b, 'a should equal b'); // Throws 'a should equal b' -``` - -Note that you may also pass an already created Error object as the second parameter, and `assert` will throw that object. - -```javascript - -var a = 1, b = 2; - -Hoek.assert(a === b, new Error('a should equal b')); // Throws the given error object -``` - -### abort(message) - -First checks if `process.env.NODE_ENV === 'test'`, and if so, throws error message. Otherwise, -displays most recent stack and then exits process. - - - -### displayStack(slice) - -Displays the trace stack - -```javascript - -var stack = Hoek.displayStack(); -console.log(stack); // returns something like: - -[ 'null (/Users/user/Desktop/hoek/test.js:4:18)', - 'Module._compile (module.js:449:26)', - 'Module._extensions..js (module.js:467:10)', - 'Module.load (module.js:356:32)', - 'Module._load (module.js:312:12)', - 'Module.runMain (module.js:492:10)', - 'startup.processNextTick.process._tickCallback (node.js:244:9)' ] -``` - -### callStack(slice) - -Returns a trace stack array. - -```javascript - -var stack = Hoek.callStack(); -console.log(stack); // returns something like: - -[ [ '/Users/user/Desktop/hoek/test.js', 4, 18, null, false ], - [ 'module.js', 449, 26, 'Module._compile', false ], - [ 'module.js', 467, 10, 'Module._extensions..js', false ], - [ 'module.js', 356, 32, 'Module.load', false ], - [ 'module.js', 312, 12, 'Module._load', false ], - [ 'module.js', 492, 10, 'Module.runMain', false ], - [ 'node.js', - 244, - 9, - 'startup.processNextTick.process._tickCallback', - false ] ] -``` - -## Function - -### nextTick(fn) - -Returns a new function that wraps `fn` in `process.nextTick`. - -```javascript - -var myFn = function () { - console.log('Do this later'); -}; - -var nextFn = Hoek.nextTick(myFn); - -nextFn(); -console.log('Do this first'); - -// Results in: -// -// Do this first -// Do this later -``` - -### once(fn) - -Returns a new function that can be run multiple times, but makes sure `fn` is only run once. - -```javascript - -var myFn = function () { - console.log('Ran myFn'); -}; - -var onceFn = Hoek.once(myFn); -onceFn(); // results in "Ran myFn" -onceFn(); // results in undefined -``` - -### ignore - -A simple no-op function. It does nothing at all. - -## Miscellaneous - -### uniqueFilename(path, extension) -`path` to prepend with the randomly generated file name. `extension` is the optional file extension, defaults to `''`. - -Returns a randomly generated file name at the specified `path`. The result is a fully resolved path to a file. - -```javascript -var result = Hoek.uniqueFilename('./test/modules', 'txt'); // results in "full/path/test/modules/{random}.txt" -``` - -### isInteger(value) - -Check `value` to see if it is an integer. Returns true/false. - -```javascript -var result = Hoek.isInteger('23') -``` diff --git a/node_modules/hapi/node_modules/hoek/images/hoek.png b/node_modules/hapi/node_modules/hoek/images/hoek.png deleted file mode 100755 index 6ccfcb12be76a7a8331428c87337b20b901e869c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37939 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.8.0" - }, - "dependencies": {}, - "devDependencies": { - "code": "1.x.x", - "lab": "5.x.x" - }, - "scripts": { - "test": "make test-cov" - }, - "license": "BSD-3-Clause", - "gitHead": "e80875a516f4b0eaa757ac4814c4510eebdcf589", - "bugs": { - "url": "https://github.com/hapijs/hoek/issues" - }, - "homepage": "https://github.com/hapijs/hoek#readme", - "_id": "hoek@2.14.0", - "_shasum": "81211691f52a5a835ae49edbf1e89c9003476aa4", - "_from": "hoek@2.14.0", - "_npmVersion": "2.9.0", - "_nodeVersion": "0.12.2", - "_npmUser": { - "name": "nlf", - "email": "quitlahok@gmail.com" - }, - "dist": { - "shasum": "81211691f52a5a835ae49edbf1e89c9003476aa4", - "tarball": "http://registry.npmjs.org/hoek/-/hoek-2.14.0.tgz" - }, - "maintainers": [ - { - "name": "hueniverse", - "email": "eran@hueniverse.com" - }, - { - "name": "wyatt", - "email": "wpreul@gmail.com" - }, - { - "name": "nlf", - "email": "quitlahok@gmail.com" - } - ], - "directories": {}, - "_resolved": "https://registry.npmjs.org/hoek/-/hoek-2.14.0.tgz", - "readme": "ERROR: No README data found!" -} diff --git a/node_modules/hapi/node_modules/hoek/test/escaper.js b/node_modules/hapi/node_modules/hoek/test/escaper.js deleted file mode 100755 index a5d048f..0000000 --- a/node_modules/hapi/node_modules/hoek/test/escaper.js +++ /dev/null @@ -1,88 +0,0 @@ -// Load modules - -var Code = require('code'); -var Hoek = require('../lib'); -var Lab = require('lab'); - - -// Declare internals - -var internals = {}; - - -// Test shortcuts - -var lab = exports.lab = Lab.script(); -var describe = lab.experiment; -var it = lab.test; -var expect = Code.expect; - - -describe('escapeJavaScript()', function () { - - it('encodes / characters', function (done) { - - var encoded = Hoek.escapeJavaScript(''); - expect(encoded).to.equal('\\x3cscript\\x3ealert\\x281\\x29\\x3c\\x2fscript\\x3e'); - done(); - }); - - it('encodes \' characters', function (done) { - - var encoded = Hoek.escapeJavaScript('something(\'param\')'); - expect(encoded).to.equal('something\\x28\\x27param\\x27\\x29'); - done(); - }); - - it('encodes large unicode characters with the correct padding', function (done) { - - var encoded = Hoek.escapeJavaScript(String.fromCharCode(500) + String.fromCharCode(1000)); - expect(encoded).to.equal('\\u0500\\u1000'); - done(); - }); - - it('doesn\'t throw an exception when passed null', function (done) { - - var encoded = Hoek.escapeJavaScript(null); - expect(encoded).to.equal(''); - done(); - }); -}); - -describe('escapeHtml()', function () { - - it('encodes / characters', function (done) { - - var encoded = Hoek.escapeHtml(''); - expect(encoded).to.equal('<script>alert(1)</script>'); - done(); - }); - - it('encodes < and > as named characters', function (done) { - - var encoded = Hoek.escapeHtml(' diff --git a/public/js/app.js b/public/js/app.js index 266e6c6..3f2884d 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -18,18 +18,50 @@ rta.controller('indexController', ['$scope', '$interval', 'dataFactory', functio }]); -rta.controller('adminController', ['$scope', 'dataFactory', function($scope, dataFactory) { - dataFactory.getRunners().success(function (runners) { - $scope.runners = runners; - }) +rta.controller('adminController', ['$scope', '$interval', 'dataFactory', function($scope, $interval, dataFactory) { - dataFactory.getLaps().success(function (laps) { - $scope.laps = laps; - }) + update_runners(); + + $scope.new_runner = {}; + + $scope.add = function(runner) { + dataFactory.addRunner(runner).success(function (newRunner) { + $scope.message = "Runner " + newRunner.name + " Added"; + update_runners(); + }) + .error(function(data, status, headers, config) { + if (status = 400){ + $scope.message = "Runner exists: " + data.bid + " " + data.name; + } else { + console.log(data); + } + }); + }; + + $interval(function(){ + + dataFactory.getNearest().success(function (nearest_device) { + $scope.new_runner.bid = nearest_device.bid; + $scope.new_runner.rssi = nearest_device.rssi; + }) + + },400); + + function update_runners() { + dataFactory.getRunners().success(function (runners) { + $scope.runners = runners; + }) + + dataFactory.getLaps().success(function (laps) { + $scope.laps = laps; + }) + } }]); + + rta.factory('dataFactory', ['$http', function($http) { var urlBase = '/'; @@ -59,10 +91,14 @@ rta.factory('dataFactory', ['$http', function($http) { return $http.post(urlBase + 'laps', lap); }; - dataFactory.getTop = function (top) { + dataFactory.getTop = function () { return $http.get(urlBase + 'top'); }; + dataFactory.getNearest = function () { + return $http.get(urlBase + 'nearest'); + }; + return dataFactory; }]); diff --git a/server/backend.js b/server/backend.js index fd38b47..f05752e 100755 --- a/server/backend.js +++ b/server/backend.js @@ -44,11 +44,15 @@ module.exports = function(server) { start_time:request.payload.team, team:request.payload.team }; - server.methods.addRunner(runner, function(err, newRunner) { + server.methods.addRunner(runner, function(err, newRunner, duplicate) { if (err) { console.log(err); } else { - reply(newRunner).code(200); + if (duplicate) { + reply(newRunner).code(400); + } else { + reply(newRunner).code(200); + } } }); }, @@ -136,8 +140,8 @@ module.exports = function(server) { method: 'GET', path: '/nearest', handler: function (request, reply) { - server.methods.getNearest( function(nearest_device) { - reply(nearest_device).code(200); + server.methods.getNearest( function(nearest_devices) { + reply(nearest_devices).code(200); }); } }); diff --git a/server/bluetooth.js b/server/bluetooth.js index b37fd1d..e653fdd 100755 --- a/server/bluetooth.js +++ b/server/bluetooth.js @@ -8,16 +8,27 @@ var WINDOW = 5000; // milliseconds module.exports = function(server) { server.method('getNearest', function (next) { - nearest_devices = inRange; + var nearest_devices = []; - console.log(inRange, nearest_devices); + for (var key in inRange) { + if (inRange.hasOwnProperty(key)) { + nearest_devices.push(inRange[key].peripheral); + } + } - - // var device = { - // nearest.peripheral.uuid: uuid, - // nearest.peripheral.rssi: rssi - // } - next(inRange); + if (nearest_devices.length > 0) { + nearest_devices = _.sortBy(nearest_devices, function(n) { + return Math.min(n.rssi); + }); + var device = { + bid: nearest_devices[0].uuid, + rssi: nearest_devices[0].rssi + } + next(device); + } else { + next(); + } + }); diff --git a/server/methods.js b/server/methods.js index 35dc02a..c31de08 100755 --- a/server/methods.js +++ b/server/methods.js @@ -19,8 +19,14 @@ module.exports = function(server) { db.runners.findOne({ bid: bid }, next); }); - server.method('addRunner', function (runner, next) { - db.runners.insert(runner, next); + server.method('addRunner', function (runner, next, duplicate) { + db.runners.findOne({ bid: runner.bid }, function(err, duplicate) { + if (duplicate) { + next(err, duplicate, true) + } else { + db.runners.insert(runner, next, false); + } + }); }); server.method('getLaps', function (next) { From 5b3382d8185fcb18744cef4ec3462972066f05d8 Mon Sep 17 00:00:00 2001 From: Paolo Memoli Date: Thu, 4 Jun 2015 00:59:23 +0200 Subject: [PATCH 10/25] added less --- package.json | 1 + public/admin.html | 4 ++-- public/css/styles.css | 3 --- public/index.html | 4 ++-- public/less/main.less | 7 +++++++ server.js | 4 +++- server/frontend.js | 15 +++++++++++++++ 7 files changed, 30 insertions(+), 8 deletions(-) delete mode 100644 public/css/styles.css create mode 100644 public/less/main.less diff --git a/package.json b/package.json index ea74ccc..42637ee 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "dependencies": { "handlebars": "3.0.x", "hapi": "8.6.x", + "hapi-less": "^0.1.1", "joi": "^6.4.3", "lodash": "^3.9.3", "nedb": "^1.1.2", diff --git a/public/admin.html b/public/admin.html index 94e0430..eb60c12 100644 --- a/public/admin.html +++ b/public/admin.html @@ -2,10 +2,10 @@ - + Runners Tracker - +
BID: {{ new_runner.rssi }}
diff --git a/public/css/styles.css b/public/css/styles.css deleted file mode 100644 index 46b6127..0000000 --- a/public/css/styles.css +++ /dev/null @@ -1,3 +0,0 @@ -html { - font-family: Arial, Helvetica, sans-serif -} \ No newline at end of file diff --git a/public/index.html b/public/index.html index eccb246..d2767de 100644 --- a/public/index.html +++ b/public/index.html @@ -2,10 +2,10 @@ - + Runners Tracker - +
-
- - Competition: -
- BID: {{ new_runner.rssi }}
- name:
- -
- -

{{ message }}

- -
    -
  • - {{ runner.name }} - {{ runner.bid }} -
  • -
- - - + + + + + diff --git a/public/js/app.js b/public/js/app.js index 3618e71..0b732e5 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -37,14 +37,23 @@ rta.controller('adminController', ['$scope', '$interval', 'dataFactory', functio $scope.comps = comps; }) + dataFactory.getTeams().success(function (teams) { + $scope.teams = teams; + }) + + + dataFactory.getCurrentComp().success(function (current){ + $scope.current_comp = current; + }) + + $scope.set_current = function (new_current) { + dataFactory.setCurrentComp(new_current) + } + $scope.add_comp = function () { dataFactory.addComp($scope.new_comp) } - $scope.set_comp = function() { - dataFactory.setComp($scope.current_comp) -} - $scope.add = function(runner) { runner.rssi = undefined; dataFactory.addRunner(runner) @@ -101,12 +110,24 @@ rta.factory('dataFactory', ['$http', function($http) { return $http.post(urlBase + 'runners', runner); }; + dataFactory.getTeams = function (teams) { + return $http.get(urlBase + 'teams') + }; + + dataFactory.addTeam = function (team) { + return $http.post(urlBase + 'teams', team) + }; + dataFactory.getComps = function () { return $http.get(urlBase + 'comps') }; - dataFactory.setComp = function (comp) { - return $http.post(urlBase + 'comps/set', comp) + dataFactory.getCurrentComp = function () { + return $http.get(urlBase + 'comps/current') + }; + + dataFactory.setCurrentComp = function (comp) { + return $http.post(urlBase + 'comps/current', { "comp_id": comp._id}) }; dataFactory.addComp = function () { diff --git a/public/less/main.less b/public/less/main.less deleted file mode 100644 index ac89cc6..0000000 --- a/public/less/main.less +++ /dev/null @@ -1,5 +0,0 @@ -html { - ul { - list-style-type: none; - } -} diff --git a/server.js b/server.js index 81b6683..76a14ab 100755 --- a/server.js +++ b/server.js @@ -16,4 +16,4 @@ server.start(function() { server.app.station_id = process.env.STATION_ID || "Finish" }); -module.exports = server; \ No newline at end of file +module.exports = server; diff --git a/server/backend.js b/server/backend.js index 8f835a9..caa0830 100755 --- a/server/backend.js +++ b/server/backend.js @@ -64,6 +64,46 @@ module.exports = function(server) { } }); + server.route({ + method: 'GET', + path: '/teams', + handler: function (request, reply) { + server.methods.getTeams(function(err, teams) { + if (err) { + console.log(err); + } else { + reply(teams).code(200); + } + }) + } + }); + + server.route({ + method: 'POST', + path: '/teams', + handler: function (request, reply) { + var team = { + name: request.payload.name, + desc:request.payload.desc, + }; + server.methods.addTeam(team, function(err, newTeam) { + if (err) { + console.log(err); + } else { + reply(newTeam).code(200); + } + }); + }, + config: { + validate: { + payload: { + name: Types.string().required().min(3), + desc: Types.string().min(3), + } + } + } + }); + server.route({ method: 'GET', path: '/laps', @@ -184,15 +224,29 @@ module.exports = function(server) { } }); + server.route({ + method: 'GET', + path: '/comps/current', + handler: function (request, reply) { + server.methods.getCurrentComp( function(err, current) { + if (err) { + console.log(err); + } else { + reply(current).code(200); + } + }); + } + }); + server.route({ method: 'POST', - path: '/comps/set', + path: '/comps/current', handler: function (request, reply) { - server.methods.setComp(request.payload.comp_id, function(err, comp) { + server.methods.setCurrentComp(request.payload.comp_id, function(err, current) { if (err) { console.log(err); } else { - reply(comp).code(200); + reply(current).code(200); } }); }, diff --git a/server/bluetooth.js b/server/bluetooth.js index c150ec3..cc8ff06 100755 --- a/server/bluetooth.js +++ b/server/bluetooth.js @@ -1,5 +1,6 @@ var noble = require('noble'); var _ = require('lodash'); +var beep = require('beepbeep') var inRange = []; var WINDOW = 5000; // milliseconds @@ -77,6 +78,7 @@ module.exports = function(server) { console.log (inRange[uuid].peripheral.rssi, inRange[uuid].peripheral.uuid); if (inRange[uuid].lastSeen < (Date.now() - WINDOW)) { + beep() console.log ('out of window', uuid); delete inRange[uuid]; @@ -85,4 +87,3 @@ module.exports = function(server) { } }, WINDOW/10); }; - diff --git a/server/methods.js b/server/methods.js index 326ba7a..df61663 100755 --- a/server/methods.js +++ b/server/methods.js @@ -8,10 +8,16 @@ var Datastore = require('nedb'); db = {}; db.runners = new Datastore({ filename: 'db/runners', autoload: true }); db.laps = new Datastore({ filename: 'db/laps', autoload: true }); -db.comp = new Datastore({ filename: 'db/comp', autoload: true }); +db.comps = new Datastore({ filename: 'db/comp', autoload: true }); +db.teams = new Datastore({ filename: 'db/teams', autoload: true }); module.exports = function(server) { + db.comps.findOne({ current: true }, function(err, current){ + server.app.current = current._id + console.log('Current Comp:', current.name) + }); + server.method('getRunners', function (next) { db.runners.find({ comp_id : server.app.current }, next); }); @@ -22,7 +28,26 @@ module.exports = function(server) { server.method('addRunner', function (runner, next) { runner.comp_id = server.app.current - db.runners.insert(runner, next); + db.runners.insert(runner, function(err, new_runner){ + if (runner.team_id) { + server.method.addRunnerToTeam(new_runner._id, runner.team_id) + new_runner.team_id = runner.team_id + } + next(err, new_runner) + }); + }); + + server.method('addTeam', function (team, next) { + team.comp_id = server.app.current + db.teams.insert(team, next); + }); + + server.method('getTeams', function (next) { + db.teams.find({ comp_id : server.app.current }, next); + }); + + server.method('addRunnerToTeam', function (runner_id, team_id, next) { + db.teams.update({ _id : team_id }, { $push: { runners: runner_id } }, next); }); server.method('getLaps', function (next) { @@ -38,43 +63,54 @@ module.exports = function(server) { }); server.method('addLap', function (lap, next) { - db.laps.findOne({ bid: lap.bid, comp_id : server.app.current }).sort({ time: -1 }).exec(function (err, lastlap) { - if (lastlap) { - lap.diff = lap.time - lastlap.time - console.log("diff:", lap.diff); - if (lap.diff > (2 * 60 * 1000)) { - lap.comp_id = server.app.current - db.laps.insert(lap, next); - } else { - console.log("time infingment:", lap.diff, lap.bid); - } - } else { - lap.diff = 0 - db.laps.insert(lap, next); - } - }) + lap.comp_id = server.app.current + db.laps.insert(lap, next); + + // db.laps.findOne({ bid: lap.bid, comp_id : server.app.current }).sort({ time: -1 }).exec(function (err, lastlap) { + // if (lastlap) { + // lap.diff = lap.time - lastlap.time + // console.log("diff:", lap.diff); + // if (lap.diff > (2 * 60 * 1000)) { + // lap.comp_id = server.app.current + // db.laps.insert(lap, next); + // } else { + // console.log("time infingment:", lap.diff, lap.bid); + // } + // } else { + // lap.diff = 0 + // db.laps.insert(lap, next); + // } + // }) }); server.method('getComp', function (comp_id, next) { - db.comp.findOne({ _id: comp_id }, next); + db.comps.findOne({ _id: comp_id }, next); }); server.method('getComps', function (next) { - db.comp.find({ }, next); + db.comps.find({ }, next); + }); + + server.method('getCurrentComp', function (next) { + db.comps.findOne({ current: true }, function(err, current){ + server.app.current = current._id + next(err, current) + }); }); - server.method('setComp', function (comp_id, next) { + server.method('setCurrentComp', function (comp_id, next) { server.app.current = comp_id - db.comp.update({ current: true }, { current: false}) - db.comp.update({ _id: comp_id }, { current: true},{}, next) + db.comps.update({ current: true }, { $unset: { current: true }}) + db.comps.update({ _id: comp_id }, { $set: {current: true}}, next) }); server.method('addComp', function (comp, next) { - db.comp.insert(comp, next); + db.comps.insert(comp, next); }); server.method('getTop', function (next) { var top = []; + console.log(server.app.current) db.runners.find({comp_id : server.app.current}, function(err, runners) { _.forEach(runners, function(runner, i) { db.laps.find({ bid: runner.bid, comp_id : server.app.current }, function(err, laps) { From b3f9b5e0b53105ac1599c473ab4d3a5604e5b7e9 Mon Sep 17 00:00:00 2001 From: Paolo Memoli Date: Mon, 22 May 2017 18:55:38 +0200 Subject: [PATCH 19/25] updated admin screen --- public/admin.html | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/public/admin.html b/public/admin.html index 4be7b43..9f919ec 100644 --- a/public/admin.html +++ b/public/admin.html @@ -6,7 +6,7 @@ Runners Tracker -
+
@@ -15,18 +15,28 @@
- {{ new_runner.bid }} {{ new_runner.rssi }} +
-
- - - {{ team._id }} +
+
+
+
+
+
+
-
- - +
+
+ + + {{ team._id }} +
+
+ + +
+
-

{{ message }}

From c0bbd5f828579fc60c01f0aba8daba39785bb856 Mon Sep 17 00:00:00 2001 From: Paolo Memoli Date: Mon, 22 May 2017 22:06:57 +0200 Subject: [PATCH 20/25] bug fixes and updating index --- public/admin.html | 62 ---------- public/admin/comps.html | 49 ++++++++ public/admin/index.html | 70 +++++++++++ public/admin/teams.html | 40 +++++++ public/index.html | 22 ++-- public/js/app.js | 254 ++++++++++++++++++++++++++-------------- server/backend.js | 17 +-- server/bluetooth.js | 150 ++++++++++++------------ server/frontend.js | 24 +++- server/methods.js | 20 ++-- 10 files changed, 453 insertions(+), 255 deletions(-) delete mode 100644 public/admin.html create mode 100644 public/admin/comps.html create mode 100644 public/admin/index.html create mode 100644 public/admin/teams.html diff --git a/public/admin.html b/public/admin.html deleted file mode 100644 index 9f919ec..0000000 --- a/public/admin.html +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - Runners Tracker - - -
-
-
- - - {{ current_comp._id }} -
-
- - -
-
-
-
-
-
-
- -
-
-
- - - {{ team._id }} -
-
- - -
- -
-
-

{{ message }}

-
-
-
-
-
    -
  • -
    {{ runner.name }}
    - {{ runner.bid }} -
  • -
-
-
-
- - - - - - - - diff --git a/public/admin/comps.html b/public/admin/comps.html new file mode 100644 index 0000000..695b5c4 --- /dev/null +++ b/public/admin/comps.html @@ -0,0 +1,49 @@ + + + + + + Runners Tracker + + + +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + Back to Admin +
+
+
+
+
    +
  • +
    {{ comp.name }}
    + {{comp.description}} + Laps: {{comp.laps}} +
  • +
+
+
+
+ + + + + + + + + diff --git a/public/admin/index.html b/public/admin/index.html new file mode 100644 index 0000000..3ae2996 --- /dev/null +++ b/public/admin/index.html @@ -0,0 +1,70 @@ + + + + + + Runners Tracker + + +
+
+
+ + + +
+
+ + + Team ID: {{ new_runner.team._id }} +
+
+ + +
+
+ + + +
+
+ + + +
+
+ +
+
+

{{ message }}

+ + +
+
+
    +
  • +
    {{ runner.name }}
    + {{ runner.bid }} +
  • +
+
+
+
+
+ + + + + + + + diff --git a/public/admin/teams.html b/public/admin/teams.html new file mode 100644 index 0000000..d667470 --- /dev/null +++ b/public/admin/teams.html @@ -0,0 +1,40 @@ + + + + + + Runners Tracker + + + +
+
+
+ + + +
+
+ +
+
+
+
+
    +
  • +
    {{ team.name }}
    +
  • +
+
+
+ Back to Admin +
+ + + + + + + + + diff --git a/public/index.html b/public/index.html index b9ede9b..c25ed62 100644 --- a/public/index.html +++ b/public/index.html @@ -3,7 +3,7 @@ - + Runners Tracker @@ -11,14 +11,14 @@
-

Leaderboard

+

Leaderboard- {{ comp.laps }} laps

@@ -27,10 +27,10 @@

Leaderboard

{{ runner.name }} {{ runner.lastlap.time | date:"m:ss.sss" }}
-
-
+
+
-
+
COMPLETE
{{ runner.laps }}
@@ -38,11 +38,11 @@

Leaderboard

- - - - - + + + + + diff --git a/public/js/app.js b/public/js/app.js index 0b732e5..b431683 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -1,162 +1,244 @@ -var rta = angular.module('runApp',[]); +var rta = angular.module('runApp', []); rta.controller('indexController', ['$scope', '$interval', 'dataFactory', function($scope, $interval, dataFactory) { - $interval(function(){ + dataFactory.getCurrentComp().success(function(comp) { + $scope.comp = comp; + }) + + $interval(function() { - dataFactory.getTop().success(function (top) { - top.forEach(function(runner){ - dataFactory.getLastLapByID(runner.bid).success(function (lastlap) { - runner.lastlap = lastlap - }) - }); + dataFactory.getTop().success(function(top) { + top.forEach(function(runner) { + dataFactory.getLastLapByID(runner.bid).success(function(lastlap) { + runner.lastlap = lastlap + }) + }); $scope.top = top; }) - },1000, 1); + }, 1000, 1); - $scope.getTimes=function(n){ - return new Array(n); + $scope.getTimes = function(n) { + return new Array(n); }; - $interval(function(){ + $interval(function() { - },1000, 1); + }, 500, 1); }]); rta.controller('adminController', ['$scope', '$interval', 'dataFactory', function($scope, $interval, dataFactory) { - update_runners(); + update_all(); $scope.new_runner = {}; $scope.current_comp = {}; - dataFactory.getComps().success(function (comps) { - $scope.comps = comps; - }) - - dataFactory.getTeams().success(function (teams) { - $scope.teams = teams; - }) - - - dataFactory.getCurrentComp().success(function (current){ - $scope.current_comp = current; - }) - - $scope.set_current = function (new_current) { + $scope.set_current = function(new_current) { dataFactory.setCurrentComp(new_current) + $scope.current_comp = new_current + update_all() } - $scope.add_comp = function () { + $scope.add_comp = function() { dataFactory.addComp($scope.new_comp) } $scope.add = function(runner) { runner.rssi = undefined; dataFactory.addRunner(runner) - .success(function (newRunner) { + .success(function(newRunner) { $scope.message = "Runner " + newRunner.name + " Added"; }) .error(function(data, status, headers, config) { - if (status = 400){ - $scope.message = "Runner exists: " + data.bid + " " + data.name; + if (status == 409) { + $scope.message = "Runner exists: " + data.bid + " " + data.name; } else { - console.log(data); + console.log(data); } }); }; - $interval(function(){ + function update_all() { + update_runners(); + dataFactory.getComps().success(function(comps) { + $scope.comps = comps; + }) + + dataFactory.getTeams().success(function(teams) { + $scope.teams = teams; + }) + } + + dataFactory.getCurrentComp().success(function(current) { + $scope.current_comp = current; + }) + + $interval(function() { update_runners(); - dataFactory.getNearest().success(function (nearest_device) { + dataFactory.getNearest().success(function(nearest_device) { $scope.new_runner.bid = nearest_device.bid; $scope.new_runner.rssi = nearest_device.rssi; }) console.log('running...'); - },500); + }, 200); function update_runners() { - dataFactory.getRunners().success(function (runners) { + dataFactory.getRunners().success(function(runners) { $scope.runners = runners; }).error(function(data, status, headers, config) { - console.log(data); + console.log(data); }); } }]); +rta.controller('teamController', ['$scope', '$interval', 'dataFactory', function($scope, $interval, dataFactory) { + + update_teams(); + + $scope.new_team = {}; + + $scope.add = function(team) { + dataFactory.addTeam(team) + .success(function(newTeam) { + $scope.message = "Team " + newTeam.name + " Added"; + $scope.new_team = {} + }) + .error(function(data, status, headers, config) { + if (status = 400) { + $scope.message = "Team exists: " + data.name; + } else { + console.log(data); + } + }); + }; + + $interval(function() { + update_teams(); + }, 500); + + function update_teams() { + dataFactory.getTeams().success(function(teams) { + $scope.teams = teams; + }) + } + +}]); + +rta.controller('compController', ['$scope', '$interval', 'dataFactory', function($scope, $interval, dataFactory) { + + update_comps(); + + $scope.new_comp = {}; + + $scope.add = function(comp) { + console.log(comp) + dataFactory.addComp(comp) + .success(function(newComp) { + $scope.message = "Competition " + newComp.name + " Added"; + $scope.new_comp = {} + }) + .error(function(data, status, headers, config) { + if (status = 400) { + $scope.message = "Team exists: " + data.name; + } else { + console.log(data); + } + }); + }; + + $interval(function() { + update_comps(); + }, 500); + + function update_comps() { + dataFactory.getComps().success(function(comps) { + $scope.comps = comps; + }) + } + +}]); + + rta.factory('dataFactory', ['$http', function($http) { - var urlBase = '/'; - var dataFactory = {}; + var urlBase = '/'; + var dataFactory = {}; - dataFactory.getRunners = function () { - return $http.get(urlBase + 'runners'); - }; + dataFactory.getRunners = function() { + return $http.get(urlBase + 'runners'); + }; - dataFactory.getRunnerByID = function (bid) { - return $http.get(urlBase + 'runners?bid=' + bid); - }; + dataFactory.getRunnerByID = function(bid) { + return $http.get(urlBase + 'runners?bid=' + bid); + }; - dataFactory.addRunner = function (runner) { - return $http.post(urlBase + 'runners', runner); - }; + dataFactory.addRunner = function(runner) { + if (runner.team) { + runner.team_id = runner.team._id; + delete runner.team + } + return $http.post(urlBase + 'runners', runner); + }; - dataFactory.getTeams = function (teams) { - return $http.get(urlBase + 'teams') - }; + dataFactory.getTeams = function(teams) { + return $http.get(urlBase + 'teams') + }; - dataFactory.addTeam = function (team) { - return $http.post(urlBase + 'teams', team) - }; + dataFactory.addTeam = function(team) { + return $http.post(urlBase + 'teams', team) + }; - dataFactory.getComps = function () { - return $http.get(urlBase + 'comps') - }; + dataFactory.getComps = function() { + return $http.get(urlBase + 'comps') + }; - dataFactory.getCurrentComp = function () { - return $http.get(urlBase + 'comps/current') - }; + dataFactory.getCurrentComp = function() { + return $http.get(urlBase + 'comps/current') + }; - dataFactory.setCurrentComp = function (comp) { - return $http.post(urlBase + 'comps/current', { "comp_id": comp._id}) - }; + dataFactory.setCurrentComp = function(comp) { + return $http.post(urlBase + 'comps/current', { + "comp_id": comp._id + }) + }; - dataFactory.addComp = function () { - return $http.post(urlBase + 'comps') - }; + dataFactory.addComp = function(comp) { + return $http.post(urlBase + 'comps', comp) + }; - dataFactory.getLaps = function () { - return $http.get(urlBase + 'laps') - }; + dataFactory.getLaps = function() { + return $http.get(urlBase + 'laps') + }; - dataFactory.getLapsByID = function (bid) { - return $http.get(urlBase + 'laps?bid=' + bid); - }; + dataFactory.getLapsByID = function(bid) { + return $http.get(urlBase + 'laps?bid=' + bid); + }; - dataFactory.getLastLapByID = function (bid) { - return $http.get(urlBase + 'lastlap?bid=' + bid); - }; + dataFactory.getLastLapByID = function(bid) { + return $http.get(urlBase + 'lastlap?bid=' + bid); + }; - dataFactory.addLaps = function (lap) { - return $http.post(urlBase + 'laps', lap); - }; + dataFactory.addLaps = function(lap) { + return $http.post(urlBase + 'laps', lap); + }; - dataFactory.getTop = function () { - return $http.get(urlBase + 'top'); - }; + dataFactory.getTop = function() { + return $http.get(urlBase + 'top'); + }; - dataFactory.getNearest = function () { - return $http.get(urlBase + 'nearest'); - }; + dataFactory.getNearest = function() { + return $http.get(urlBase + 'nearest'); + }; - return dataFactory; + return dataFactory; }]); diff --git a/server/backend.js b/server/backend.js index caa0830..607f205 100755 --- a/server/backend.js +++ b/server/backend.js @@ -42,13 +42,16 @@ module.exports = function(server) { bid: request.payload.bid, name: request.payload.name, start_time:request.payload.start_time, - team:request.payload.team, + team_id:request.payload.team_id, }; server.methods.addRunner(runner, function(err, newRunner) { if (err) { console.log(err); + if (err.errorType) { + reply("Runner Exists").code(409) + } } else { - reply(newRunner).code(200); + reply(newRunner).code(201); } }); }, @@ -58,7 +61,7 @@ module.exports = function(server) { bid: Types.string().required().min(3), name: Types.string().required().min(3), start_time: Types.date(), - team: Types.string(), + team_id: Types.string(), } } } @@ -148,7 +151,7 @@ module.exports = function(server) { if (err) { console.log(err); } else { - reply(newLap).code(200); + reply(newLap).code(201); } }); }, @@ -205,11 +208,11 @@ module.exports = function(server) { laps: request.payload.laps, desc: request.payload.desc, }; - server.methods.addComp(comp, function(err, comp) { + server.methods.addComp(comp, function(err, new_comp) { if (err) { console.log(err); } else { - reply(comp).code(200); + reply(new_comp).code(201); } }); }, @@ -246,7 +249,7 @@ module.exports = function(server) { if (err) { console.log(err); } else { - reply(current).code(200); + reply(current).code(201); } }); }, diff --git a/server/bluetooth.js b/server/bluetooth.js index cc8ff06..1e1db41 100755 --- a/server/bluetooth.js +++ b/server/bluetooth.js @@ -3,87 +3,87 @@ var _ = require('lodash'); var beep = require('beepbeep') var inRange = []; -var WINDOW = 5000; // milliseconds +var WINDOW = 5000; // milliseconds module.exports = function(server) { - server.method('getNearest', function (next) { - var nearest_devices = []; - - for (var key in inRange) { - if (inRange.hasOwnProperty(key)) { - nearest_devices.push(inRange[key].peripheral); - } - } - - if (nearest_devices.length > 0) { - nearest_devices = _.sortBy(nearest_devices, function(n) { - return Math.min(n.rssi); - }); - var device = { - bid: nearest_devices[0].uuid, - rssi: nearest_devices[0].rssi - } - next(device); - } else { - next(); - } - + server.method('getNearest', function(next) { + var nearest_devices = []; + + for (var key in inRange) { + if (inRange.hasOwnProperty(key)) { + nearest_devices.push(inRange[key].peripheral); + } + } + + if (nearest_devices.length > 0) { + nearest_devices = _.sortBy(nearest_devices, function(n) { + return Math.min(n.rssi); + }); + var device = { + bid: nearest_devices[0].uuid, + rssi: nearest_devices[0].rssi + } + next(device); + } else { + next(); + } + + }); + + + + function addLap(uuid) { + var lap = { + bid: uuid, + time: new Date(), + station: server.app.station_id + } + server.methods.logLap(lap); + server.methods.addLap(lap, function(err, newLap) { + if (err) { + console.log(err); + } else { + console.log(newLap); + } }); + } + + noble.on('stateChange', function(state) { + if (state === 'poweredOn') { + noble.startScanning([], true); + } else { + noble.stopScanning([], true); + } + }); + + noble.on('discover', function(peripheral) { + + var uuid = peripheral.uuid; + + if (!inRange[uuid]) { + inRange[uuid] = { + peripheral: peripheral + }; + addLap(uuid) + } + inRange[uuid].lastSeen = Date.now(); + inRange[uuid].peripheral.rssi = peripheral.rssi; + }); + + setInterval(function() { + for (var uuid in inRange) { + + console.log(inRange[uuid].peripheral.rssi, inRange[uuid].peripheral.uuid); + if (inRange[uuid].lastSeen < (Date.now() - WINDOW)) { + // beep() + console.log('out of window', uuid); + delete inRange[uuid]; + } - function addLap(uuid){ - var lap = { - bid: uuid, - time: new Date(), - station: server.app.station_id - } - server.methods.logLap(lap); - server.methods.addLap(lap, function(err, newLap) { - if (err) { - console.log(err); - } else { - console.log(newLap); - } - }); - } - - noble.on('stateChange', function(state) { - if (state === 'poweredOn') { - noble.startScanning([],true); - } else { - noble.stopScanning([],true); - } - }); - - noble.on('discover', function(peripheral) { - - var uuid = peripheral.uuid; - - if (!inRange[uuid]) { - inRange[uuid] = { - peripheral: peripheral - }; - addLap(uuid) - } - inRange[uuid].lastSeen = Date.now(); - inRange[uuid].peripheral.rssi = peripheral.rssi; - }); - - setInterval(function() { - for (var uuid in inRange) { - - console.log (inRange[uuid].peripheral.rssi, inRange[uuid].peripheral.uuid); - - if (inRange[uuid].lastSeen < (Date.now() - WINDOW)) { - beep() - console.log ('out of window', uuid); - - delete inRange[uuid]; - } - - } - }, WINDOW/10); + } + }, WINDOW / 10); }; diff --git a/server/frontend.js b/server/frontend.js index e6d70d7..1ea9080 100755 --- a/server/frontend.js +++ b/server/frontend.js @@ -13,7 +13,25 @@ module.exports = function(server) { path: '/admin', handler: { file: { - path: 'public/admin.html' + path: 'public/admin/index.html' + } + } + }); + server.route({ + method: 'GET', + path: '/admin/teams', + handler: { + file: { + path: 'public/admin/teams.html' + } + } + }); + server.route({ + method: 'GET', + path: '/admin/comps', + handler: { + file: { + path: 'public/admin/comps.html' } } }); @@ -36,9 +54,9 @@ module.exports = function(server) { } } }, function (err) { - + if (err) { console.log('Failed loading hapi-less'); } }); -}; \ No newline at end of file +}; diff --git a/server/methods.js b/server/methods.js index df61663..50124e5 100755 --- a/server/methods.js +++ b/server/methods.js @@ -11,6 +11,10 @@ db.laps = new Datastore({ filename: 'db/laps', autoload: true }); db.comps = new Datastore({ filename: 'db/comp', autoload: true }); db.teams = new Datastore({ filename: 'db/teams', autoload: true }); +db.runners.ensureIndex({ fieldName: 'bid', unique: true }, function (err) { +}); + + module.exports = function(server) { db.comps.findOne({ current: true }, function(err, current){ @@ -27,14 +31,8 @@ module.exports = function(server) { }); server.method('addRunner', function (runner, next) { - runner.comp_id = server.app.current - db.runners.insert(runner, function(err, new_runner){ - if (runner.team_id) { - server.method.addRunnerToTeam(new_runner._id, runner.team_id) - new_runner.team_id = runner.team_id - } - next(err, new_runner) - }); + runner.comp_id = server.app.current + db.runners.insert(runner, next); }); server.method('addTeam', function (team, next) { @@ -46,9 +44,9 @@ module.exports = function(server) { db.teams.find({ comp_id : server.app.current }, next); }); - server.method('addRunnerToTeam', function (runner_id, team_id, next) { - db.teams.update({ _id : team_id }, { $push: { runners: runner_id } }, next); - }); + // server.method('addRunnerToTeam', function (runner_id, team_id, next) { + // db.teams.update({ _id : team_id }, { $push: { runners: runner_id } }, next); + // }); server.method('getLaps', function (next) { db.laps.find({ comp_id : server.app.current }, next); From 9aac1da2d61c11b148e73b1216b74d8d680633f2 Mon Sep 17 00:00:00 2001 From: Paolo Memoli Date: Tue, 23 May 2017 00:48:17 +0200 Subject: [PATCH 21/25] added recent and goto routes and pages --- public/index.html | 49 ++++++++++++++++++++++++++++++--------------- public/js/app.js | 17 ++++++++-------- public/togo.html | 41 +++++++++++++++++++++++++++++++++++++ server/backend.js | 14 +++++++++++++ server/bluetooth.js | 7 ++++--- server/frontend.js | 9 +++++++++ server/methods.js | 21 ++++++++++++++----- 7 files changed, 125 insertions(+), 33 deletions(-) create mode 100644 public/togo.html diff --git a/public/index.html b/public/index.html index c25ed62..627021b 100644 --- a/public/index.html +++ b/public/index.html @@ -4,7 +4,7 @@ - + Runners Tracker @@ -16,28 +16,45 @@
-
-
-

Leaderboard- {{ comp.laps }} laps

-
-
+
+
+

Leaderboard + - {{ comp.laps }} laps +

+
+
-
-
-
-
{{ runner.name }} {{ runner.lastlap.time | date:"m:ss.sss" }}
-
-
+
+
+ + +
+
+

{{ runner.name }}

+
+
+
+
+ COMPLETE +
+
{{ runner.laps }}
+
-
- COMPLETE + + +
+
+

{{ runner.name }}

+
{{runner.time}}
+
-
{{ runner.laps }}
+ + +
-
diff --git a/public/js/app.js b/public/js/app.js index b431683..62fd1b5 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -17,16 +17,11 @@ rta.controller('indexController', ['$scope', '$interval', 'dataFactory', functio $scope.top = top; }) - }, 1000, 1); - - $scope.getTimes = function(n) { - return new Array(n); - }; - - $interval(function() { - - }, 500, 1); + dataFactory.getRecents().success(function(recent_runners) { + $scope.recent_runners = recent_runners + }) + }, 1000); }]); @@ -240,5 +235,9 @@ rta.factory('dataFactory', ['$http', function($http) { return $http.get(urlBase + 'nearest'); }; + dataFactory.getRecents = function() { + return $http.get(urlBase + 'recents'); + }; + return dataFactory; }]); diff --git a/public/togo.html b/public/togo.html new file mode 100644 index 0000000..3ee82ba --- /dev/null +++ b/public/togo.html @@ -0,0 +1,41 @@ + + + + + + + + Runners Tracker + + + + + +
+
+
+
+ + +
+
+

{{ runner.name }}

+
{{ comp.laps - runner.laps }} Remaining
+
+
+
+
+
+
+ + + + + + + + diff --git a/server/backend.js b/server/backend.js index 607f205..6d4b516 100755 --- a/server/backend.js +++ b/server/backend.js @@ -281,4 +281,18 @@ module.exports = function(server) { }); } }); + + server.route({ + method: 'GET', + path: '/recents', + handler: function (request, reply) { + server.methods.getRecents( function(err, recent_runners) { + if (err) { + console.log(err); + } else { + reply(recent_runners).code(200); + } + }); + } + }); }; diff --git a/server/bluetooth.js b/server/bluetooth.js index 1e1db41..cfb8d27 100755 --- a/server/bluetooth.js +++ b/server/bluetooth.js @@ -35,9 +35,10 @@ module.exports = function(server) { function addLap(uuid) { + time = new Date() var lap = { bid: uuid, - time: new Date(), + time: time.getTime(), station: server.app.station_id } server.methods.logLap(lap); @@ -75,11 +76,11 @@ module.exports = function(server) { setInterval(function() { for (var uuid in inRange) { - console.log(inRange[uuid].peripheral.rssi, inRange[uuid].peripheral.uuid); + // console.log(inRange[uuid].peripheral.rssi, inRange[uuid].peripheral.uuid); if (inRange[uuid].lastSeen < (Date.now() - WINDOW)) { // beep() - console.log('out of window', uuid); + // console.log('out of window', uuid); delete inRange[uuid]; } diff --git a/server/frontend.js b/server/frontend.js index 1ea9080..0e659be 100755 --- a/server/frontend.js +++ b/server/frontend.js @@ -8,6 +8,15 @@ module.exports = function(server) { } } }); + server.route({ + method: 'GET', + path: '/togo', + handler: { + file: { + path: 'public/togo.html' + } + } + }); server.route({ method: 'GET', path: '/admin', diff --git a/server/methods.js b/server/methods.js index 50124e5..02831b4 100755 --- a/server/methods.js +++ b/server/methods.js @@ -11,15 +11,20 @@ db.laps = new Datastore({ filename: 'db/laps', autoload: true }); db.comps = new Datastore({ filename: 'db/comp', autoload: true }); db.teams = new Datastore({ filename: 'db/teams', autoload: true }); -db.runners.ensureIndex({ fieldName: 'bid', unique: true }, function (err) { -}); +// db.runners.ensureIndex({ fieldName: 'bid', unique: true }, function (err) { +// }); module.exports = function(server) { db.comps.findOne({ current: true }, function(err, current){ - server.app.current = current._id - console.log('Current Comp:', current.name) + if (current){ + server.app.current = current._id + console.log('Current Comp:', current.name) + } else { + console.log('No Current Comp, Set in admin') + } + }); server.method('getRunners', function (next) { @@ -62,6 +67,7 @@ module.exports = function(server) { server.method('addLap', function (lap, next) { lap.comp_id = server.app.current + db.runners.update({ bid : lap.bid, comp_id : server.app.current },{ $inc: { laps: 1 }, $set: {recent: true}},{}) db.laps.insert(lap, next); // db.laps.findOne({ bid: lap.bid, comp_id : server.app.current }).sort({ time: -1 }).exec(function (err, lastlap) { @@ -108,7 +114,6 @@ module.exports = function(server) { server.method('getTop', function (next) { var top = []; - console.log(server.app.current) db.runners.find({comp_id : server.app.current}, function(err, runners) { _.forEach(runners, function(runner, i) { db.laps.find({ bid: runner.bid, comp_id : server.app.current }, function(err, laps) { @@ -138,4 +143,10 @@ module.exports = function(server) { if (err){console.log(err)}; }); }); + + server.method('getRecents', function (next) { + db.laps.find({ comp_id : server.app.current}).sort({ time: 1 }).limit(15).projection({ bid:1, _id: 0 }).exec(function(err, recent_laps){ + db.runners.find({ $or: recent_laps, comp_id : server.app.current }, next) + }); + }); }; From 45863a1c0a5e68a543476a1ad1803e22bf448882 Mon Sep 17 00:00:00 2001 From: Paolo Memoli Date: Tue, 23 May 2017 21:51:56 +0200 Subject: [PATCH 22/25] added start time --- public/admin/index.html | 14 +- public/index.html | 3 +- public/js/app.js | 19 +++ public/togo.html | 5 +- server/backend.js | 21 +++ server/bluetooth.js | 5 +- server/methods.js | 332 ++++++++++++++++++++++++++-------------- 7 files changed, 274 insertions(+), 125 deletions(-) diff --git a/public/admin/index.html b/public/admin/index.html index 3ae2996..e7d97d6 100644 --- a/public/admin/index.html +++ b/public/admin/index.html @@ -13,6 +13,11 @@
+
+ + Manage Teams + Manage Competitions +
@@ -37,16 +42,11 @@
- +

{{ message }}

- +
diff --git a/public/index.html b/public/index.html index 627021b..fb367e3 100644 --- a/public/index.html +++ b/public/index.html @@ -32,7 +32,8 @@

Leaderboard

{{ runner.name }}

-
+ +
diff --git a/public/js/app.js b/public/js/app.js index 62fd1b5..de33bb0 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -57,6 +57,19 @@ rta.controller('adminController', ['$scope', '$interval', 'dataFactory', functio }); }; + $scope.start = function(start_time) { + if (start_time == 'now'){ + start_time = (new Date()).getTime(); + } + dataFactory.setCurrentStart(start_time) + .success(function(response) { + $scope.message = "Competition started"; + }) + .error(function(response) { + $scope.message = "Error occured: " + response; + }); + }; + function update_all() { update_runners(); dataFactory.getComps().success(function(comps) { @@ -207,6 +220,12 @@ rta.factory('dataFactory', ['$http', function($http) { }) }; + dataFactory.setCurrentStart = function(start_time) { + return $http.post(urlBase + 'comps/start', { + "start_time": start_time + }) + }; + dataFactory.addComp = function(comp) { return $http.post(urlBase + 'comps', comp) }; diff --git a/public/togo.html b/public/togo.html index 3ee82ba..a5e2f20 100644 --- a/public/togo.html +++ b/public/togo.html @@ -21,10 +21,11 @@
-
+

{{ runner.name }}

-
{{ comp.laps - runner.laps }} Remaining
+ {{ runner }} +
{{ comp.laps }} - {{ runner.laps }} Remaining
diff --git a/server/backend.js b/server/backend.js index 6d4b516..c9b6205 100755 --- a/server/backend.js +++ b/server/backend.js @@ -262,6 +262,27 @@ module.exports = function(server) { } }); + server.route({ + method: 'POST', + path: '/comps/start', + handler: function (request, reply) { + server.methods.setCurrentStart(request.payload.start_time, function(err, current) { + if (err) { + console.log(err); + } else { + reply(current).code(201); + } + }); + }, + config: { + validate: { + payload: { + start_time: Types.number().integer(), + } + } + } + }); + server.route({ method: 'GET', path: '/top', diff --git a/server/bluetooth.js b/server/bluetooth.js index cfb8d27..7110096 100755 --- a/server/bluetooth.js +++ b/server/bluetooth.js @@ -33,15 +33,14 @@ module.exports = function(server) { }); - function addLap(uuid) { - time = new Date() + time = new Date(); var lap = { bid: uuid, time: time.getTime(), station: server.app.station_id } - server.methods.logLap(lap); + server.methods.logLap(lap) server.methods.addLap(lap, function(err, newLap) { if (err) { console.log(err); diff --git a/server/methods.js b/server/methods.js index 02831b4..6408c52 100755 --- a/server/methods.js +++ b/server/methods.js @@ -6,147 +6,255 @@ var visitor = ua('UA-27923958-9'); var Datastore = require('nedb'); db = {}; -db.runners = new Datastore({ filename: 'db/runners', autoload: true }); -db.laps = new Datastore({ filename: 'db/laps', autoload: true }); -db.comps = new Datastore({ filename: 'db/comp', autoload: true }); -db.teams = new Datastore({ filename: 'db/teams', autoload: true }); +db.runners = new Datastore({ + filename: 'db/runners', + autoload: true +}); +db.laps = new Datastore({ + filename: 'db/laps', + autoload: true +}); +db.comps = new Datastore({ + filename: 'db/comp', + autoload: true +}); +db.teams = new Datastore({ + filename: 'db/teams', + autoload: true +}); // db.runners.ensureIndex({ fieldName: 'bid', unique: true }, function (err) { // }); - module.exports = function(server) { - db.comps.findOne({ current: true }, function(err, current){ - if (current){ - server.app.current = current._id - console.log('Current Comp:', current.name) - } else { - console.log('No Current Comp, Set in admin') - } + db.comps.findOne({ + current: true + }, function(err, current) { + if (current) { + server.app.start_time = current.start_time + server.app.current = current._id + console.log('Current Comp:', current.name) + } else { + console.log('No Current Comp, Set in admin') + } - }); + }); - server.method('getRunners', function (next) { - db.runners.find({ comp_id : server.app.current }, next); - }); + server.method('getRunners', function(next) { + db.runners.find({ + comp_id: server.app.current + }, next); + }); - server.method('getRunnerByID', function (bid, next) { - db.runners.findOne({ bid: bid, comp_id : server.app.current }, next); - }); + server.method('getRunnerByID', function(bid, next) { + db.runners.findOne({ + bid: bid, + comp_id: server.app.current + }, next); + }); - server.method('addRunner', function (runner, next) { - runner.comp_id = server.app.current - db.runners.insert(runner, next); - }); + server.method('addRunner', function(runner, next) { + runner.comp_id = server.app.current + db.runners.insert(runner, next); + }); - server.method('addTeam', function (team, next) { - team.comp_id = server.app.current - db.teams.insert(team, next); - }); + server.method('addTeam', function(team, next) { + team.comp_id = server.app.current + db.teams.insert(team, next); + }); - server.method('getTeams', function (next) { - db.teams.find({ comp_id : server.app.current }, next); - }); + server.method('getTeams', function(next) { + db.teams.find({ + comp_id: server.app.current + }, next); + }); - // server.method('addRunnerToTeam', function (runner_id, team_id, next) { - // db.teams.update({ _id : team_id }, { $push: { runners: runner_id } }, next); - // }); + // server.method('addRunnerToTeam', function (runner_id, team_id, next) { + // db.teams.update({ _id : team_id }, { $push: { runners: runner_id } }, next); + // }); - server.method('getLaps', function (next) { - db.laps.find({ comp_id : server.app.current }, next); - }); + server.method('getLaps', function(next) { + db.laps.find({ + comp_id: server.app.current + }, next); + }); - server.method('getLapsByID', function (bid, next) { - db.laps.find({ bid: bid, comp_id : server.app.current }, next); - }); + server.method('getLapsByID', function(bid, next) { + db.laps.find({ + bid: bid, + comp_id: server.app.current + }, next); + }); - server.method('getLastLapByID', function (bid, next) { - db.laps.findOne({ bid: bid, comp_id : server.app.current }).sort({ time: -1 }).exec(next); - }); + server.method('getLastLapByID', function(bid, next) { + db.laps.findOne({ + bid: bid, + comp_id: server.app.current + }).sort({ + time: -1 + }).exec(next); + }); + + server.method('addLap', function(lap, next) { + time = new Date() + current_time = time.getTime() - server.method('addLap', function (lap, next) { - lap.comp_id = server.app.current - db.runners.update({ bid : lap.bid, comp_id : server.app.current },{ $inc: { laps: 1 }, $set: {recent: true}},{}) + if (server.app.start_time && current_time > server.app.start_time) { + lap.comp_id = server.app.current; + db.runners.update({ + bid: lap.bid, + comp_id: server.app.current + }, { + $inc: { + laps: 1 + } + }, {}) db.laps.insert(lap, next); + } else { + console.log("Comp not started"); + } - // db.laps.findOne({ bid: lap.bid, comp_id : server.app.current }).sort({ time: -1 }).exec(function (err, lastlap) { - // if (lastlap) { - // lap.diff = lap.time - lastlap.time - // console.log("diff:", lap.diff); - // if (lap.diff > (2 * 60 * 1000)) { - // lap.comp_id = server.app.current - // db.laps.insert(lap, next); - // } else { - // console.log("time infingment:", lap.diff, lap.bid); - // } - // } else { - // lap.diff = 0 - // db.laps.insert(lap, next); - // } - // }) - }); + // db.laps.findOne({ bid: lap.bid, comp_id : server.app.current }).sort({ time: -1 }).exec(function (err, lastlap) { + // if (lastlap) { + // lap.diff = lap.time - lastlap.time + // console.log("diff:", lap.diff); + // if (lap.diff > (2 * 60 * 1000)) { + // lap.comp_id = server.app.current + // db.laps.insert(lap, next); + // } else { + // console.log("time infingment:", lap.diff, lap.bid); + // } + // } else { + // lap.diff = 0 + // db.laps.insert(lap, next); + // } + // }) + }); - server.method('getComp', function (comp_id, next) { - db.comps.findOne({ _id: comp_id }, next); - }); + server.method('getComp', function(comp_id, next) { + db.comps.findOne({ + _id: comp_id + }, next); + }); - server.method('getComps', function (next) { - db.comps.find({ }, next); - }); + server.method('getComps', function(next) { + db.comps.find({}, next); + }); - server.method('getCurrentComp', function (next) { - db.comps.findOne({ current: true }, function(err, current){ - server.app.current = current._id - next(err, current) - }); - }); + server.method('addComp', function(comp, next) { + db.comps.insert(comp, next); + }); - server.method('setCurrentComp', function (comp_id, next) { - server.app.current = comp_id - db.comps.update({ current: true }, { $unset: { current: true }}) - db.comps.update({ _id: comp_id }, { $set: {current: true}}, next) + server.method('getCurrentComp', function(next) { + db.comps.findOne({ + current: true + }, function(err, current) { + server.app.current = current._id + next(err, current) }); + }); - server.method('addComp', function (comp, next) { - db.comps.insert(comp, next); - }); + server.method('setCurrentComp', function(comp_id, next) { + server.app.current = comp_id + db.comps.update({ + current: true + }, { + $unset: { + current: true + } + }) + db.comps.update({ + _id: comp_id + }, { + $set: { + current: true + } + }, next) + }); + + server.method('setCurrentStart', function(start_time, next) { + server.app.start_time = start_time + db.comps.update({ + _id: server.app.current + }, { + $set: { + 'start_time': server.app.start_time + } + }, next) + }); - server.method('getTop', function (next) { - var top = []; - db.runners.find({comp_id : server.app.current}, function(err, runners) { - _.forEach(runners, function(runner, i) { - db.laps.find({ bid: runner.bid, comp_id : server.app.current }, function(err, laps) { - if (laps) { - top.push({ - name: runner.name, - laps: laps.length, - bid: runner.bid - }) - } - if (i == runners.length-1) { - top = _.sortBy(top, 'laps').reverse(); - next(top); - } - }) + server.method('getTop', function(next) { + var top = []; + db.runners.find({ + comp_id: server.app.current + }, function(err, runners) { + _.forEach(runners, function(runner, i) { + db.laps.find({ + bid: runner.bid, + comp_id: server.app.current + }, function(err, laps) { + if (laps) { + top.push({ + name: runner.name, + laps: laps.length, + bid: runner.bid }) + } + if (i == runners.length - 1) { + top = _.sortBy(top, 'laps').reverse(); + next(top); + } }) - }); + }) + }) + }); - server.method('logLap', function (lap) { - visitor.event({ - ec:'Runner Tracking', - ea:'Runner Passed', - el: lap.time, - ev: lap.bid - }, function (err) { - if (err){console.log(err)}; - }); + server.method('logLap', function(lap) { + visitor.event({ + ec: 'Runner Tracking', + ea: 'Runner Passed', + el: lap.time, + ev: lap.bid + }, function(err) { + if (err) { + console.log(err) + }; }); + }); - server.method('getRecents', function (next) { - db.laps.find({ comp_id : server.app.current}).sort({ time: 1 }).limit(15).projection({ bid:1, _id: 0 }).exec(function(err, recent_laps){ - db.runners.find({ $or: recent_laps, comp_id : server.app.current }, next) - }); - }); + server.method('getRecents', function(next) { + var recents = []; + db.laps.find({ + comp_id: server.app.current + }).sort({ + time: 1 + }).limit(15).projection({ + bid: 1, + _id: 0 + }).exec(function(err, recent_laps) { + db.runners.find({ + $or: recent_laps, + comp_id: server.app.current + }, function(err, runners) { + _.forEach(runners, function(runner, i) { + db.laps.find({ + bid: runner.bid, + comp_id: server.app.current + }, function(err, laps) { + if (laps) { + recents.push({ + name: runner.name, + laps: laps.length, + bid: runner.bid + }) + } + if (i == runners.length - 1) { + next(recents); + } + }) + }) + }) + }) + }) }; From 504f6d64deaba99a158086245c3b328c29d20975 Mon Sep 17 00:00:00 2001 From: Paolo Memoli Date: Tue, 23 May 2017 22:36:24 +0200 Subject: [PATCH 23/25] fixed lap counting bug --- public/admin/index.html | 2 +- public/togo.html | 4 +--- server/methods.js | 29 ++++++++++------------------- 3 files changed, 12 insertions(+), 23 deletions(-) diff --git a/public/admin/index.html b/public/admin/index.html index e7d97d6..fdf0975 100644 --- a/public/admin/index.html +++ b/public/admin/index.html @@ -14,7 +14,7 @@
- + Manage Teams Manage Competitions
diff --git a/public/togo.html b/public/togo.html index a5e2f20..1110bba 100644 --- a/public/togo.html +++ b/public/togo.html @@ -19,13 +19,11 @@
-

{{ runner.name }}

- {{ runner }} -
{{ comp.laps }} - {{ runner.laps }} Remaining
+
{{ comp.laps - runner.laps }} Remaining
diff --git a/server/methods.js b/server/methods.js index 6408c52..598e01b 100755 --- a/server/methods.js +++ b/server/methods.js @@ -175,6 +175,15 @@ module.exports = function(server) { server.method('setCurrentStart', function(start_time, next) { server.app.start_time = start_time + db.laps.remove({ + comp_id: server.app.current + },{ multi: true }) + db.runners.update({ comp_id: server.app.current + }, { + $set: { + laps: 0 + } + },{ multi: true }) db.comps.update({ _id: server.app.current }, { @@ -236,25 +245,7 @@ module.exports = function(server) { db.runners.find({ $or: recent_laps, comp_id: server.app.current - }, function(err, runners) { - _.forEach(runners, function(runner, i) { - db.laps.find({ - bid: runner.bid, - comp_id: server.app.current - }, function(err, laps) { - if (laps) { - recents.push({ - name: runner.name, - laps: laps.length, - bid: runner.bid - }) - } - if (i == runners.length - 1) { - next(recents); - } - }) - }) - }) + }, next) }) }) }; From 1f5c638362b06cd5b51d36ce263f457da1493fca Mon Sep 17 00:00:00 2001 From: Paolo Memoli Date: Tue, 23 May 2017 22:43:10 +0200 Subject: [PATCH 24/25] simplified top --- server/backend.js | 6 +- server/methods.js | 401 ++++++++++++++++++++++++---------------------- 2 files changed, 213 insertions(+), 194 deletions(-) diff --git a/server/backend.js b/server/backend.js index c9b6205..2f3fd3a 100755 --- a/server/backend.js +++ b/server/backend.js @@ -287,8 +287,12 @@ module.exports = function(server) { method: 'GET', path: '/top', handler: function (request, reply) { - server.methods.getTop( function(top) { + server.methods.getTop( function(err, top) { + if (err) { + console.log(err); + } else { reply(top).code(200); + } }); } }); diff --git a/server/methods.js b/server/methods.js index 598e01b..cc488b9 100755 --- a/server/methods.js +++ b/server/methods.js @@ -28,224 +28,239 @@ db.teams = new Datastore({ module.exports = function(server) { - db.comps.findOne({ - current: true - }, function(err, current) { - if (current) { - server.app.start_time = current.start_time - server.app.current = current._id - console.log('Current Comp:', current.name) - } else { - console.log('No Current Comp, Set in admin') - } +db.comps.findOne({ + current: true +}, function(err, current) { + if (current) { + server.app.start_time = current.start_time + server.app.current = current._id + console.log('Current Comp:', current.name) + } else { + console.log('No Current Comp, Set in admin') + } - }); +}); - server.method('getRunners', function(next) { - db.runners.find({ - comp_id: server.app.current - }, next); - }); +server.method('getRunners', function(next) { + db.runners.find({ + comp_id: server.app.current + }, next); +}); - server.method('getRunnerByID', function(bid, next) { - db.runners.findOne({ - bid: bid, - comp_id: server.app.current - }, next); - }); +server.method('getRunnerByID', function(bid, next) { + db.runners.findOne({ + bid: bid, + comp_id: server.app.current + }, next); +}); - server.method('addRunner', function(runner, next) { - runner.comp_id = server.app.current - db.runners.insert(runner, next); - }); +server.method('addRunner', function(runner, next) { + runner.comp_id = server.app.current + db.runners.insert(runner, next); +}); - server.method('addTeam', function(team, next) { - team.comp_id = server.app.current - db.teams.insert(team, next); - }); +server.method('addTeam', function(team, next) { + team.comp_id = server.app.current + db.teams.insert(team, next); +}); - server.method('getTeams', function(next) { - db.teams.find({ - comp_id: server.app.current - }, next); - }); +server.method('getTeams', function(next) { + db.teams.find({ + comp_id: server.app.current + }, next); +}); - // server.method('addRunnerToTeam', function (runner_id, team_id, next) { - // db.teams.update({ _id : team_id }, { $push: { runners: runner_id } }, next); - // }); +// server.method('addRunnerToTeam', function (runner_id, team_id, next) { +// db.teams.update({ _id : team_id }, { $push: { runners: runner_id } }, next); +// }); - server.method('getLaps', function(next) { - db.laps.find({ - comp_id: server.app.current - }, next); - }); +server.method('getLaps', function(next) { + db.laps.find({ + comp_id: server.app.current + }, next); +}); - server.method('getLapsByID', function(bid, next) { - db.laps.find({ - bid: bid, - comp_id: server.app.current - }, next); - }); +server.method('getLapsByID', function(bid, next) { + db.laps.find({ + bid: bid, + comp_id: server.app.current + }, next); +}); + +server.method('getLastLapByID', function(bid, next) { + db.laps.findOne({ + bid: bid, + comp_id: server.app.current + }).sort({ + time: -1 + }).exec(next); +}); - server.method('getLastLapByID', function(bid, next) { - db.laps.findOne({ - bid: bid, +server.method('addLap', function(lap, next) { + time = new Date() + current_time = time.getTime() + + if (server.app.start_time && current_time > server.app.start_time) { + lap.comp_id = server.app.current; + db.runners.update({ + bid: lap.bid, comp_id: server.app.current - }).sort({ - time: -1 - }).exec(next); - }); + }, { + $inc: { + laps: 1 + } + }, {}) + db.laps.insert(lap, next); + } else { + console.log("Comp not started"); + } - server.method('addLap', function(lap, next) { - time = new Date() - current_time = time.getTime() - - if (server.app.start_time && current_time > server.app.start_time) { - lap.comp_id = server.app.current; - db.runners.update({ - bid: lap.bid, - comp_id: server.app.current - }, { - $inc: { - laps: 1 - } - }, {}) - db.laps.insert(lap, next); - } else { - console.log("Comp not started"); - } + // db.laps.findOne({ bid: lap.bid, comp_id : server.app.current }).sort({ time: -1 }).exec(function (err, lastlap) { + // if (lastlap) { + // lap.diff = lap.time - lastlap.time + // console.log("diff:", lap.diff); + // if (lap.diff > (2 * 60 * 1000)) { + // lap.comp_id = server.app.current + // db.laps.insert(lap, next); + // } else { + // console.log("time infingment:", lap.diff, lap.bid); + // } + // } else { + // lap.diff = 0 + // db.laps.insert(lap, next); + // } + // }) +}); - // db.laps.findOne({ bid: lap.bid, comp_id : server.app.current }).sort({ time: -1 }).exec(function (err, lastlap) { - // if (lastlap) { - // lap.diff = lap.time - lastlap.time - // console.log("diff:", lap.diff); - // if (lap.diff > (2 * 60 * 1000)) { - // lap.comp_id = server.app.current - // db.laps.insert(lap, next); - // } else { - // console.log("time infingment:", lap.diff, lap.bid); - // } - // } else { - // lap.diff = 0 - // db.laps.insert(lap, next); - // } - // }) - }); +server.method('getComp', function(comp_id, next) { + db.comps.findOne({ + _id: comp_id + }, next); +}); - server.method('getComp', function(comp_id, next) { - db.comps.findOne({ - _id: comp_id - }, next); - }); +server.method('getComps', function(next) { + db.comps.find({}, next); +}); - server.method('getComps', function(next) { - db.comps.find({}, next); - }); +server.method('addComp', function(comp, next) { + db.comps.insert(comp, next); +}); - server.method('addComp', function(comp, next) { - db.comps.insert(comp, next); +server.method('getCurrentComp', function(next) { + db.comps.findOne({ + current: true + }, function(err, current) { + server.app.current = current._id + next(err, current) }); +}); - server.method('getCurrentComp', function(next) { - db.comps.findOne({ +server.method('setCurrentComp', function(comp_id, next) { + server.app.current = comp_id + db.comps.update({ + current: true + }, { + $unset: { current: true - }, function(err, current) { - server.app.current = current._id - next(err, current) - }); - }); - - server.method('setCurrentComp', function(comp_id, next) { - server.app.current = comp_id - db.comps.update({ + } + }) + db.comps.update({ + _id: comp_id + }, { + $set: { current: true - }, { - $unset: { - current: true - } - }) - db.comps.update({ - _id: comp_id - }, { - $set: { - current: true - } - }, next) - }); + } + }, next) +}); + +server.method('setCurrentStart', function(start_time, next) { + server.app.start_time = start_time + db.laps.remove({ + comp_id: server.app.current + }, { + multi: true + }) + db.runners.update({ + comp_id: server.app.current + }, { + $set: { + laps: 0 + } + }, { + multi: true + }) + db.comps.update({ + _id: server.app.current + }, { + $set: { + 'start_time': server.app.start_time + } + }, next) +}); + +server.method('getTop', function(next) { + + db.runners.find({ + comp_id: server.app.current + }).sort({ + laps: -1 + }).limit(15).exec(next) +}) - server.method('setCurrentStart', function(start_time, next) { - server.app.start_time = start_time - db.laps.remove({ - comp_id: server.app.current - },{ multi: true }) - db.runners.update({ comp_id: server.app.current - }, { - $set: { - laps: 0 - } - },{ multi: true }) - db.comps.update({ - _id: server.app.current - }, { - $set: { - 'start_time': server.app.start_time - } - }, next) - }); - server.method('getTop', function(next) { - var top = []; - db.runners.find({ - comp_id: server.app.current - }, function(err, runners) { - _.forEach(runners, function(runner, i) { - db.laps.find({ - bid: runner.bid, - comp_id: server.app.current - }, function(err, laps) { - if (laps) { - top.push({ - name: runner.name, - laps: laps.length, - bid: runner.bid - }) - } - if (i == runners.length - 1) { - top = _.sortBy(top, 'laps').reverse(); - next(top); - } - }) - }) - }) - }); - server.method('logLap', function(lap) { - visitor.event({ - ec: 'Runner Tracking', - ea: 'Runner Passed', - el: lap.time, - ev: lap.bid - }, function(err) { - if (err) { - console.log(err) - }; - }); + +// var top = []; +// db.runners.find({ +// comp_id: server.app.current +// }, function(err, runners) { +// _.forEach(runners, function(runner, i) { +// db.laps.find({ +// bid: runner.bid, +// comp_id: server.app.current +// }, function(err, laps) { +// if (laps) { +// top.push({ +// name: runner.name, +// laps: laps.length, +// bid: runner.bid +// }) +// } +// if (i == runners.length - 1) { +// top = _.sortBy(top, 'laps').reverse(); +// next(top); +// } +// }) +// }) +// }) + +server.method('logLap', function(lap) { + visitor.event({ + ec: 'Runner Tracking', + ea: 'Runner Passed', + el: lap.time, + ev: lap.bid + }, function(err) { + if (err) { + console.log(err) + }; }); +}); - server.method('getRecents', function(next) { - var recents = []; - db.laps.find({ +server.method('getRecents', function(next) { + var recents = []; + db.laps.find({ + comp_id: server.app.current + }).sort({ + time: 1 + }).limit(15).projection({ + bid: 1, + _id: 0 + }).exec(function(err, recent_laps) { + db.runners.find({ + $or: recent_laps, comp_id: server.app.current - }).sort({ - time: 1 - }).limit(15).projection({ - bid: 1, - _id: 0 - }).exec(function(err, recent_laps) { - db.runners.find({ - $or: recent_laps, - comp_id: server.app.current - }, next) - }) + }, next) }) +}) }; From e2ed4b93f896b9f79199421b73eadb44af13d93c Mon Sep 17 00:00:00 2001 From: James Greenaway Date: Tue, 19 Dec 2017 13:39:15 +0000 Subject: [PATCH 25/25] update readme --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 7d0ae55..9874c0c 100755 --- a/README.md +++ b/README.md @@ -1,21 +1,21 @@ -#Runner Tracker -##A simple app to track runners and count number of laps. +# Runner Tracker -- HAPI backend -- NEDB database -- Noble bluetooth detection -- Angular Frontend +An app to automatcially track runners and count laps. It uses Bluetooth Low Energy to sense runners and a mobile web app to display the data. -Designed to be run remotely on a PI with a bluetooth 4.0 dongle + Bluetooth 4.0 tags on runners. +Designed to be run in the field on a RaspberryPi with a Bluetooth 4.0 dongle along with Bluetooth 4.0 tags attached to the runners. -to run: +## Stack -## if on linux/Pi: +- [Noble](https://github.com/sandeepmistry/noble) for Bluetooth detection +- HAPI back-end with NEDB database +- Angular front-end + +## Dependencies 1. `sudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev` 2. `sudo setcap cap_net_raw+eip $(eval readlink -f which node)` -## all: +## Start 1. `npm install` 2. set ENVS `export STATION_ID=Test`

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 JSEyC!{{R6A+M@sf diff --git a/images/products.png b/images/products.png deleted file mode 100755 index 6ba92fc38747bd5683f63599dd54707a32841813..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 70351 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 Vp" + this.body + ""; + return new Handlebars.SafeString("" + Handlebars.Utils.escapeExpression(this.body) + ""); }); var context = { posts: [{url: "/hello-world", body: "Hello World!"}] }; -var source = "